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;
}

 

posted @ 2018-03-02 20:27  312432424  阅读(103)  评论(0编辑  收藏  举报