BZOJ 2120: 数颜色 带修改的莫队算法 树状数组套主席树
https://www.lydsy.com/JudgeOnline/problem.php?id=2120
标题里是两种不同的解法。
带修改的莫队和普通莫队比多了个修改操作,影响不大,但是注意一下细节不要出现zz错误。
这道题修改的数量比较少可以写莫队,但是如果修改数量多或者是特别极限的数据大概是不行的吧。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 const int maxn=10010; 7 using namespace std; 8 int n,m; 9 char ch[3]={}; 10 int clo[maxn]={},las[maxn]={}; 11 struct node{ 12 int pos,clo,pre; 13 }t[maxn];int tr=0; 14 struct nod{ 15 int l,r,id,pre; 16 }q[maxn];int tq=0; 17 int b[maxn]={},ans[maxn]={},ans1=0; 18 int vis[maxn*100]={}; 19 bool mcmp(nod aa,nod bb){ 20 return (b[aa.l]==b[bb.l])?((aa.r==bb.r)?aa.id<bb.id:aa.r<bb.r):(b[aa.l]<b[bb.l]); 21 } 22 void doit(int x,int v){ 23 if(v){ 24 if(!vis[clo[x]])ans1++; 25 vis[clo[x]]++; 26 } 27 else{ 28 if(vis[clo[x]]==1)ans1--; 29 vis[clo[x]]--; 30 } 31 } 32 void change(int x,int y,int v){ 33 //cout<<x<<y<<clo[x]<<v<<endl; 34 if(v){ 35 doit(x,0); 36 clo[x]=y; 37 doit(x,1); 38 }clo[x]=y; 39 } 40 void work(){ 41 int l=1,r=0,now=0; 42 for(int i=1;i<=tq;i++){ 43 while(now<q[i].pre){now++;change(t[now].pos,t[now].clo,l<=t[now].pos&&t[now].pos<=r);} 44 while(now>q[i].pre){change(t[now].pos,t[now].pre,l<=t[now].pos&&t[now].pos<=r);now--;} 45 while(r<q[i].r)doit(++r,1); 46 while(l>q[i].l)doit(--l,1); 47 while(r>q[i].r){doit(r,0);--r;} 48 while(l<q[i].l){doit(l,0);++l;} 49 ans[q[i].id]=ans1; 50 } 51 for(int i=1;i<=tq;i++){ 52 printf("%d\n",ans[i]); 53 } 54 } 55 int main(){ 56 scanf("%d%d",&n,&m); 57 for(int i=1;i<=n;i++){scanf("%d",&clo[i]);las[i]=clo[i];} 58 int x,y; 59 for(int i=1;i<=m;i++){ 60 scanf("%s",ch);scanf("%d%d",&x,&y); 61 if(ch[0]=='Q'){ q[++tq].l=x; q[tq].r=y; q[tq].id=tq; q[tq].pre=tr; } 62 else{ t[++tr].pos=x; t[tr].clo=y;t[tr].pre=las[x];las[x]=y;} 63 }int siz=(int)sqrt((double)n); 64 for(int i=1;i<=n;i++)b[i]=(i-1)/siz+1; 65 sort(q+1,q+1+tq,mcmp); 66 work(); 67 return 0; 68 }