bzoj 2120
对每一个位置上的颜色求一个前驱,表示上一次这个颜色出现的位置。
求 [ l , r ] 范围内有多少种不同的颜色,可以转化成求 [ l , r ] 有多少个位置的前驱在 [ 0 , l - 1 ]。
于是就可以树状数组套主席树。
每次修改 p 位置的颜色为 col 要考虑这样三种情况:
( 1 ) 前驱为 p 的位置的前驱改为 p 的前驱
( 2 ) p 的前驱改为 p 后面第一个颜色为 col 的位置的前驱
( 3 ) p 后面第一个颜色为 col 的位置的前驱改为 p
使用 set 来维护即可。
#include"cstdio" #include"cctype" #include"set" #include"algorithm" using namespace std; const int N=10001,M=10001,C=20001,O=3920001; int read() { int c,x=0; while(!isdigit(c=getchar())); while(x=x*10+c-'0',isdigit(c=getchar())); return x; } int n,m,cnt,now,a[N],b[C],pre[N],hed[C],c[O][2],s[O]; char ch[M]; int x[M],y[M]; set<int> col[C]; int r[N]; void change(int &o,int l,int r,int w,int v) { if(w<l || w>r) return; if(!o) o=++now; s[o]+=v; if(l==r) return; int mid=l+r>>1; change(c[o][0],l,mid,w,v); change(c[o][1],mid+1,r,w,v); } int query(int o,int l,int r,int v) { if(l>v) return 0; if(r<=v) return s[o]; int mid=l+r>>1; return query(c[o][0],l,mid,v)+query(c[o][1],mid+1,r,v); } void add(int i,int w,int v) { for(;i<=n;i+=i&-i) change(r[i],0,n,w,v); } int sum(int i,int v) { int res=0; for(;i;i-=i&-i) res+=query(r[i],0,n,v); return res; } int main() { n=read(),m=read(); cnt=n; for(int i=1;i<=n;i++) a[i]=b[i]=read(); for(int i=1;i<=m;i++) { while(ch[i]=getchar(),ch[i]!='Q' && ch[i]!='R'); x[i]=read();y[i]=read(); if(ch[i]=='R') b[++cnt]=y[i]; } sort(b+1,b+cnt+1); cnt=unique(b+1,b+cnt+1)-b-1; for(int i=1;i<=cnt;i++) col[i].insert(n+1),col[i].insert(0); for(int i=1;i<=n;i++) { a[i]=lower_bound(b+1,b+cnt+1,a[i])-b; col[a[i]].insert(i); pre[i]=hed[a[i]]; hed[a[i]]=i; add(i,pre[i],1); } for(int i=1;i<=m;i++) { if(ch[i]=='R') { y[i]=lower_bound(b+1,b+cnt+1,y[i])-b; if(y[i]==a[x[i]]) continue; add(x[i],pre[x[i]],-1); set<int>::iterator it=col[a[x[i]]].upper_bound(x[i]); if(*it!=n+1) { add(*it,pre[*it],-1); pre[*it]=pre[x[i]]; add(*it,pre[*it],1); } it=col[y[i]].upper_bound(x[i]); if(*it!=n+1) { add(*it,pre[*it],-1); pre[x[i]]=pre[*it]; pre[*it]=x[i]; add(*it,pre[*it],1); } else pre[x[i]]=*(--it); add(x[i],pre[x[i]],1); col[a[x[i]]].erase(x[i]); a[x[i]]=y[i]; col[y[i]].insert(x[i]); } else printf("%d\n",sum(y[i],x[i]-1)-sum(x[i]-1,x[i]-1)); } return 0; }