zoukankan      html  css  js  c++  java
  • [国家集训队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
    ",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;
    }
    
  • 相关阅读:
    centos 6.5 查看、开启,关闭 端口
    centos 安装 nginx
    centos 安装 svn
    centos 安装 maven
    (转)不停止Nginx服务的情况下平滑变更Nginx配置
    记录1---python+linux+vim之while循环语句使用
    记录1---linux系统之创建用户,用户登录,查看用户名,切换用户登录,退出登录
    记录——Fiddler5.0 中文版 绿色免费版 汉化破解版安装
    fiddler笔记1---fiddler的安装 和 证书安装 以及 证书导出失败问题解决
    fiddler笔记2--fiddler工具界面的功能使用与介绍
  • 原文地址:https://www.cnblogs.com/xzz_233/p/8321150.html
Copyright © 2011-2022 走看看