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

/**************************************************************
    Problem: 2120
    User: wangyucheng
    Language: C++
    Result: Accepted
    Time:1748 ms
    Memory:50220 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;
#define N 13000
#define M 1050000
#define inf 0x3fffffff
int 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;
            bb[nod]=p;
            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);
        }
    }
}

 

posted @ 2014-07-16 22:56  wangyucheng  阅读(232)  评论(0编辑  收藏  举报