题目描述
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:
1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。
2、 R P Col 把第P支画笔替换为颜色Col。
为了满足墨墨的要求,你知道你需要干什么了吗?
输入输出格式
输入格式:第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。
第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。
第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
输出格式:对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
输入输出样例
说明
对于100%的数据,N≤50000,M≤50000,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
本题可能轻微卡常数
来源:bzoj2120
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。
题解:
可修改莫队模板题。
对于可修改的,我们显然把块分成n^2/3最优(我也不太清楚为什么)
代码:
#include<bits/stdc++.h> using namespace std; struct aaa{ int l,r,tim,id; }c[100001],d[100001]; int Q,R,n,m,n1,ll,rr,a[100001],aa[100001],color[1000001],be[100001],ans,axs[100001]; bool cmp(aaa a,aaa b){ return be[a.l]==be[b.l]?(be[a.r]==be[b.r]?a.tim<b.tim:a.r<b.r):a.l<b.l; } void xiu(int x,int t){ color[x]+=t; if(t>0)ans+=color[x]==1; else ans-=color[x]==0; } void going(int x,int t1){ if(ll<=x&&x<=rr){ xiu(t1,1);xiu(aa[x],-1); } aa[x]=t1; } int main(){ char cc; int t,k,i; scanf("%d%d",&n,&m); n1=pow(n,0.666666); for(i=1;i<=n;i++){ be[i]=(i-1)/n1+1; } for(i=1;i<=n;i++){ scanf("%d",&a[i]); aa[i]=a[i]; } for(i=1;i<=m;i++){ scanf(" %c %d%d",&cc,&t,&k); if(cc=='Q'){ Q++;c[Q].id=Q; c[Q].l=t;c[Q].r=k;c[Q].tim=R; } else{ R++; d[R].l=t;d[R].r=a[t];d[R].tim=k;a[t]=k; } } n1=0;ll=1; sort(c+1,c+Q+1,cmp); for(i=1;i<=Q;i++){ while(n1<c[i].tim)going(d[n1+1].l,d[n1+1].tim),n1++; while(n1>c[i].tim)going(d[n1].l,d[n1].r),n1--; while(ll<c[i].l)xiu(aa[ll++],-1); while(ll>c[i].l)xiu(aa[--ll],1); while(rr<c[i].r)xiu(aa[++rr],1); while(rr>c[i].r)xiu(aa[rr--],-1); axs[c[i].id]=ans; } for(i=1;i<=Q;i++)printf("%d\n",axs[i]); }