首页 > 代码库 > bzoj 2120: 数颜色 线段树套平衡树

bzoj 2120: 数颜色 线段树套平衡树

/**************************************************************    Problem: 2120    User: wangyucheng    Language: C++    Result: Time_Limit_Exceed****************************************************************/ #include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<set>using namespace std;#define N 13000#define M 1050000#define inf 0x3fffffffint ch[M][2],pre[M],siz[M],val[M],ne[N];int col[N];int rt[N*4],L[N*4],R[N*4];int bb[M];set<int> jj[1000010];void up(int x){   siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;    }void rot(int x){   int y=pre[x],z=pre[y];   int k=ch[y][0]==x;   pre[ch[y][!k]=ch[x][k]]=y;   pre[ch[x][k]=y]=x;   pre[x]=z;   if(!z)rt[bb[y]]=x;   else ch[z][ch[z][1]==y]=x;   up(y);   }void splay(int x,int f){    int y,z;    for(;pre[x]!=f;){        y=pre[x],z=pre[y];        if(z==f)rot(x);        else if((ch[y][1]==x)==(ch[z][1]==y))rot(y),rot(x);        else rot(x),rot(x);    }    up(x);}int n,m;int nod;int mk[N];void select(int p,int k,int f){    int x=rt[p];    while(siz[ch[x][0]]+1!=k){        if(siz[ch[x][0]]>=k)x=ch[x][0];        else k-=siz[ch[x][0]]+1,x=ch[x][1];     }    splay(x,f);}int Bui(int l,int r,int p){    if(l>r)return 0;    int k=++nod;    bb[k]=p;    int mid=l+r>>1;    val[k]=mk[mid];    pre[ch[k][0]=Bui(l,mid-1,p)]=k;    pre[ch[k][1]=Bui(mid+1,r,p)]=k;    up(k);    return k;}void build(int l,int r,int k){    for(int i=2;i<=r-l+2;i++)mk[i]=ne[l+i-2];    mk[1]=-inf;    mk[r-l+3]=inf;    L[k]=l,R[k]=r;    sort(mk+1,mk+r-l+4);    rt[k]=Bui(1,r-l+3,k);    if(l==r)return;    int mid=l+r>>1;    build(l,mid,k<<1);    build(mid+1,r,k<<1|1);}int find(int p,int vv){    int x=rt[p];    int ma,as=-1;    while(x){        if(val[x]<=vv){           if(as==-1||val[x]>ma)as=x,ma=val[x];           x=ch[x][1];              }else x=ch[x][0];    }    return as;}int count(int p,int vv){   int as=find(p,vv);    splay(as,0);    return siz[ch[as][0]];}void dele(int p,int vv){    int x=find(p,vv);   splay(x,0);   int k=siz[ch[x][0]]+1;   select(p,k-1,0);   select(p,k+1,rt[p]);       ch[ch[rt[p]][1]][0]=0;   splay(ch[rt[p]][1],0);}void ins(int p,int vv){    int x=rt[p],k;    while(1){       k=vv>val[x];       if(!ch[x][k]){            pre[ch[x][k]=++nod]=x;            val[nod]=vv;            splay(nod,0);          break;            }        x=ch[x][k];     }}void change(int l,int k,int vv){    dele(k,ne[l]);    ins(k,vv);    if(L[k]==R[k])return;   if(R[k<<1]>=l)change(l,k<<1,vv);   else change(l,k<<1|1,vv);}int ans;void ask(int l,int r,int k,int vv){    if(L[k]>=l&&R[k]<=r){ans+=count(k,vv);return;}    if(L[k<<1]<=r&&R[k<<1]>=l)ask(l,r,k<<1,vv);    if(L[k<<1|1]<=r&&R[k<<1|1]>=l)ask(l,r,k<<1|1,vv);}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)scanf("%d",&col[i]),jj[col[i]].insert(i);    for(int i=1;i<=n;i++){         int u=col[i];         set<int>::iterator it=jj[u].upper_bound(i);         if(it==jj[u].end())ne[i]=n+i;         else ne[i]=*it;        }    build(1,n,1);    for(int i=1;i<=m;i++){        char a;        int b,c;        scanf(" %c%d%d",&a,&b,&c);        if(a==R){            set<int>::iterator it=jj[col[b]].find(b),it2,it3;             it3=it;            it3++;            if(it!=jj[col[b]].begin()){                   it2=it;                   it2--;                     if(it3==jj[col[b]].end())change(*it2,1,*it2+n),ne[*it2]=*it2+n;                   else change(*it2,1,*it3),ne[*it2]=*it3;            }            jj[col[b]].erase(it);            jj[c].insert(b);            it=jj[c].find(b);            it2=jj[c].upper_bound(b);            if(it2!=jj[c].end())change(b,1,*it2),ne[b]=*it2;            else change(b,1,b+n),ne[b]=b+n;            it3=it;            if(it!=jj[c].begin()){               it3--;               change(*it3,1,b);               ne[*it3]=b;              }                   col[b]=c;        }else{            ans=0;            ask(b,c,1,c);            printf("%d\n",c-b+1-ans);        }    }}
View Code