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 }
View Code

 

posted @ 2018-04-04 12:00  鲸头鹳  阅读(221)  评论(1编辑  收藏  举报