• BZOJ 3065 替罪羊树+动态开节点线段树


    思路:

    RT

    可以看VFK的题解

    我写了半天拍了半天...

    不过是$nlog^2n$的

    要写垃圾回收的

    线段树 如果某个节点的sum是0  也可以free掉

    //By SiriusRen
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=70000;
    int root[200005],n,q,xx,yy,zz,Root,ans;
    struct Segment_Tree{
        int rubbish[30000005],top,tree[30000005],lson[30000005],rson[30000005];
        int get_rubbish(){if(rubbish[top])return rubbish[top--];return top--;}
        void insert(int l,int r,int &pos,int num,int wei){
            if(!pos)pos=get_rubbish();
            if(l==r){tree[pos]+=wei;return;}
            int mid=(l+r)>>1;
            if(mid>=num)insert(l,mid,lson[pos],num,wei);
            else insert(mid+1,r,rson[pos],num,wei);
            tree[pos]=tree[lson[pos]]+tree[rson[pos]];
            if(!tree[lson[pos]]&&lson[pos])rubbish[++top]=lson[pos],lson[pos]=0;
            if(!tree[rson[pos]]&&rson[pos])rubbish[++top]=rson[pos],rson[pos]=0;
        }
        void merge(int x,int y,int &k){
            if(!k)k=get_rubbish();
            tree[k]=tree[x]+tree[y];
            if(lson[x]||lson[y])merge(lson[x],lson[y],lson[k]);
            if(rson[x]||rson[y])merge(rson[x],rson[y],rson[k]);
        }
        void dfs(int l,int r,int x){
            int mid=(l+r)>>1;
            if(lson[x])dfs(l,mid,lson[x]),rubbish[++top]=lson[x];
            if(rson[x])dfs(mid+1,r,rson[x]),rubbish[++top]=rson[x];
            lson[x]=rson[x]=tree[x]=0;
        }
    }segtree;
    int top1,top2,stk1[200005],stk2[200005];
    struct SC_TREE{
        int top,rubbish[200005],lson[200005],rson[200005],wei[200005],size[200005];
        int get_rubbish(){return rubbish[top--];}
        void build(int &k,int l,int r){
            if(l>r)return;
            if(!k)k=get_rubbish();
            int mid=(l+r)>>1;wei[k]=stk2[mid];
            if(l==r){segtree.insert(0,N,root[k],stk2[l],1),size[k]=1;return;}
            build(lson[k],l,mid-1),build(rson[k],mid+1,r);
            segtree.merge(root[lson[k]],root[rson[k]],root[k]);
            segtree.insert(0,N,root[k],stk2[mid],1);
            size[k]=size[lson[k]]+size[rson[k]]+1;
        }
        void init(){for(int i=1;i<=200000;i++)rubbish[i]=200000-i+1;top=200000;segtree.top=30000000,build(Root,1,n);}
        int find_wei(int x,int sz){
            if(size[lson[x]]+1==sz)return wei[x];
            else if(size[lson[x]]>=sz)return find_wei(lson[x],sz);
            else return find_wei(rson[x],sz-size[lson[x]]-1);
        }
        void change(int x,int sz,int w,int last_w){
            segtree.insert(0,N,root[x],last_w,-1);
            segtree.insert(0,N,root[x],w,1);
            if(size[lson[x]]+1==sz){wei[x]=w;return;}
            else if(size[lson[x]]>=sz)change(lson[x],sz,w,last_w);
            else change(rson[x],sz-size[lson[x]]-1,w,last_w);
        }
        void query(int l,int r,int x){
            int L=size[lson[x]],R=size[x];
            if(l==1&&R==r){stk1[++top1]=root[x];return;}
            if(l<=L+1&&r>=L+1)stk2[++top2]=wei[x];
            if(r<=L)query(l,r,lson[x]);
            else if(l>L+1)query(l-L-1,r-L-1,rson[x]);
            else{
                if(l<=L)query(l,L,lson[x]);
                if(r>L+1)query(1,r-L-1,rson[x]); 
            }
        }
        int Query(int l,int r,int kth){
            top1=top2=0;query(l,r,Root);
            int L=0,R=N,ans=0,M,temp;
            while(L<R){
                M=(L+R)>>1;temp=0;
                for(int i=1;i<=top1;i++)temp+=segtree.tree[segtree.lson[stk1[i]]];
                for(int i=1;i<=top2;i++)if(stk2[i]<=M&&stk2[i]>=L)temp++;
                if(temp>kth){for(int i=1;i<=top1;i++)stk1[i]=segtree.lson[stk1[i]];R=M;}
                else {for(int i=1;i<=top1;i++)stk1[i]=segtree.rson[stk1[i]];L=M+1;kth-=temp;}
            }return L;
        }
        void dfs(int x){
            segtree.dfs(0,N,root[x]);root[x]=0;
            if(lson[x])dfs(lson[x]),rubbish[++top]=lson[x];
            stk2[++top2]=wei[x];
            if(rson[x])dfs(rson[x]),rubbish[++top]=rson[x];
            lson[x]=rson[x]=wei[x]=size[x]=0;
        }
        int rebuild(int sz,int &x){top2=0,dfs(x),build(x,1,sz);}
        bool insert(int &x,int sz,int w){
            if(!x){x=get_rubbish();segtree.insert(0,N,root[x],w,1);size[x]=1;wei[x]=w;return 0;}
            segtree.insert(0,N,root[x],w,1),size[x]++;
            if(size[lson[x]]>=sz){if(insert(lson[x],sz,w))rebuild(size[lson[x]],lson[x]);}
            else if(insert(rson[x],sz-size[lson[x]]-1,w))rebuild(size[rson[x]],rson[x]);
            if(max(size[lson[x]],size[rson[x]])>0.666*size[x])return 1;return 0;
        }
    }SC_Tree;
    int read(){
        int x=0;char p=getchar();
        while(p<'0'||p>'9')p=getchar();
        while(p>='0'&&p<='9')x=x*10+p-'0',p=getchar();
        return x;
    }
    char readchar(){char p=getchar();while(p!='Q'&&p!='M'&&p!='I')p=getchar();return p;}
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&stk2[i]);
        SC_Tree.init();
        scanf("%d",&q);
        while(q--){
            char op=readchar();xx=read()^ans,yy=read()^ans;
            if(op=='Q')zz=read()^ans,printf("%d
    ",ans=SC_Tree.Query(xx,yy,zz-1));
            else if(op=='M')SC_Tree.change(Root,xx,yy,SC_Tree.find_wei(Root,xx));
            else SC_Tree.insert(Root,xx-1,yy);
        }
    }
  • 相关阅读:
    Math对象
    MDN中的对象原型
    构造函数的静态成员和实例成员
    js对象的九大特点
    对象数据的使用方法
    创建对象的所有方式
    Linux下gcc编译器的使用
    Linux vim环境设置
    Linux下is not in the sudoers file解决方法
    mySQL相关函数的使用
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532778.html
Copyright © 2020-2023  润新知