[国家集训队2011]数颜色

很久以前写的,但因为拿来出题一直没敢FA题解。。。

这是一份树套树的题解,n,m<=50000应该是可以跑的。

HH的项链题解

在那份题解里我写了树套树,其实是因为我要来写这道题懒得改了。。。。

首先维护100000颗平衡树,每个平衡树里的点颜色一样,这样可以方便的求出同种颜色的前驱后继和修改

然后树状数组套主席树,修改的话搞出lst值就可以辣

// It is made by XZZ
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<set>
#define il inline
#define rg register
#define vd void
#define sta static
typedef long long ll;
typedef const int& fast;
using namespace std;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int maxn=10000;
int n,m;
namespace Tree{
    namespace SGT{
        const double alpha=0.7233333;
        int root[1000001],id,val[maxn*50],ch[maxn*50][2],siz[maxn*50],cover[maxn*50],b[maxn*50];
        bool del[maxn*50];
        il int newnode(int _val){val[++id]=_val,ch[id][0]=ch[id][1]=0,siz[id]=cover[id]=1;return id;}
        il vd dfs(const int&rt){
            if(!rt)return;
            dfs(ch[rt][0]);
            if(!del[rt])b[++b[0]]=rt;
            dfs(ch[rt][1]);
        }
        il int divide(int l,int r){
            if(l>r)return 0;
            int mid=(l+r)>>1;
            ch[b[mid]][0]=divide(l,mid-1);
            ch[b[mid]][1]=divide(mid+1,r);
            siz[b[mid]]=siz[ch[b[mid]][0]]+siz[ch[b[mid]][1]]+!del[b[mid]];
            cover[b[mid]]=cover[ch[b[mid]][0]]+cover[ch[b[mid]][1]]+1;
            return b[mid];
        }
        il vd rebuild(int&rt){b[0]=0;dfs(rt);rt=divide(1,b[0]);}
        il int*_Insert(int&rt,fast num){
            if(!rt){rt=newnode(num);return NULL;}
            ++siz[rt],++cover[rt];
            int*ret=_Insert(ch[rt][num>=val[rt]],num);
            if(max(cover[ch[rt][0]],cover[ch[rt][1]])>alpha*cover[rt])ret=&rt;
            return ret;
        }
        il vd Insert(fast y,fast x){int*ls=_Insert(root[y],x);if(ls)rebuild(*ls);}
        il int Rank(fast y,fast x){
            int ret=1,now=root[y];
            while(now)
                if(x<=val[now])now=ch[now][0];
                else ret+=siz[ch[now][0]]+!del[now],now=ch[now][1];
            return ret;
        }
        il vd _Delete(fast y,int k){
            int now=root[y];
            while(now){
                --siz[now];
                if(!del[now]&&k==siz[ch[now][0]]+1){del[now]=1;return;}
                if(k<=siz[ch[now][0]])now=ch[now][0];
                else k-=siz[ch[now][0]]+!del[now],now=ch[now][1];
            }
        }
        il vd Delete(fast y,fast x){
            _Delete(y,Rank(y,x));
            if(siz[root[y]]<cover[root[y]]*alpha)rebuild(root[y]);
        }
    }
    il int lb(fast x){return x&-x;}
    il vd Update(rg int x,fast y){if(!x)return;while(x<=n)SGT::Insert(x,y),x+=lb(x);}
    il vd Update_(rg int x,fast y){if(!x)return;while(x<=n)SGT::Delete(x,y),x+=lb(x);}
    il int Query(rg int l,rg int r,fast y){
        int ret=0;
        while(r)ret+=SGT::Rank(r,y+1)-1,r-=lb(r);
        --l;while(l)ret-=SGT::Rank(l,y+1)-1,l-=lb(l);
        return ret;
    }
}
namespace Set FA♂Q{
    set<int>st[1000001];
    il vd del(fast x,fast y){st[x].erase(st[x].find(y));}
    il vd ins(fast x,fast y){st[x].insert(y);}
    il pair<int,int>find(fast x,fast y){
        set<int>::iterator it=st[x].find(y);
        pair<int,int>ret=make_pair(0,0);
        if(it!=st[x].begin())--it,ret.first=*it,++it;
        ++it;if(it!=st[x].end())ret.second=*it;
        return ret;
    }
}
int num[maxn],__lst[1000001];
int main(){
    n=gi();m=gi();
    for(rg int i=1;i<=n;++i)num[i]=gi(),Tree::Update(i,__lst[num[i]]),Set::ins(num[i],i),__lst[num[i]]=i;
    int x,y;pair<int,int>s;char opt[10];
    while(m--){
        scanf("%s",opt),x=gi(),y=gi();
        if(opt[0]=='Q')printf("%d\n",Tree::Query(x,y,x-1));
        else{
            s=Set::find(num[x],x);
            Tree::Update_(x,s.first),Tree::Update_(s.second,x),Tree::Update(s.second,s.first);
            Set::del(num[x],x),Set::ins((num[x]=y),x);
            s=Set::find(num[x],x);
            Tree::Update_(s.second,s.first),Tree::Update(s.second,x),Tree::Update(x,s.first);
        }
    }
    return 0;
}
posted @ 2018-01-20 16:41  菜狗xzz  阅读(1106)  评论(1编辑  收藏  举报