zoukankan      html  css  js  c++  java
  • 树套树代码

    树状数组套线段树:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define maxn 500001
    
    int n,m,ai[maxn],root[maxn],pos[maxn],mis[maxn];
    int K,ch[maxn*25][2],dis[25*maxn],tot,to,po,mi,sum,mid;
    
    char Cget;
    
    inline void in(int &now)
    {
        Cget=getchar();now=0;
        while(Cget>'9'||Cget<'0') Cget=getchar();
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
    }
    
    inline int lowbit(int x)
    {
        return x&(-x);
    }
    
    void tree_add(int &now,int l,int r)
    {
        if(!now) now=++tot;
        dis[now]+=K;
        if(l==r) return ;
        int mid=l+r>>1;
        if(to<=mid) tree_add(ch[now][0],l,mid);
        else tree_add(ch[now][1],mid+1,r);
    }
    
    void add(int x)
    {
        while(x<=n)
        {
            tree_add(root[x],1,n);
            x+=lowbit(x);
        }
    }
    
    int query(int li,int ri)
    {
        po=0,mi=0,sum=0,mid=(ri-li>>1)+1;
        while(ri)
        {
            if(root[ri])
            {
                pos[++po]=root[ri];
                sum+=dis[pos[po]];
            }
            ri-=lowbit(ri);
        }
        while(li)
        {
            if(root[li])
            {
                mis[++mi]=root[li];
                sum-=dis[mis[mi]];
            }
            li-=lowbit(li);
        }
        int l=1,r=n;
        while(l!=r)
        {
            int k=0;
            for(int i=1;i<=po;i++)
            {
                if(pos[i]&&ch[pos[i]][0]) k+=dis[ch[pos[i]][0]];
            }
            for(int i=1;i<=mi;i++)
            {
                if(mis[i]&&ch[mis[i]][0]) k-=dis[ch[mis[i]][0]];
            }
            if(k>=mid)
            {
                sum=k;
                for(int i=1;i<=po;i++) if(pos[i]) pos[i]=ch[pos[i]][0];
                for(int i=1;i<=mi;i++) if(mis[i]) mis[i]=ch[mis[i]][0];
                r=l+r>>1;
            }
            else if(sum-k>=mid)
            {
                sum-=k;
                for(int i=1;i<=po;i++) if(pos[i]) pos[i]=ch[pos[i]][1];
                for(int i=1;i<=mi;i++) if(mis[i]) mis[i]=ch[mis[i]][1];
                l=(l+r>>1)+1;
            }
            else return -1;
        }
        if(sum>=mid) return l;
    }
    
    int main()
    {
        in(n),in(m);int l,r,s,k;
        for(int i=1;i<=n;i++) in(ai[i]),to=ai[i],K=1,add(i);
        for(;m--;)
        {
            in(l),in(r),in(s),in(k);
            int p=query(l-1,r);
            if(p!=-1) s=p;
            for(;k--;)
            {
                in(p);
                to=ai[p],K=-1,add(p);
                ai[p]=s;
                to=s,K=1,add(p);
            }
            printf("%d
    ",s);
        }
        printf("%d
    ",query(0,n));
        return 0;
    }

    线段树套平衡树:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define maxn 500001
    
    struct TreeNodeType {
        int w,key,size;
                
        TreeNodeType *ch[2],*opi;
                
        TreeNodeType()
        {
            ch[0]=ch[1]=opi=NULL;
        }
    };
    
    class SegmentTreeNodeType {
        private:
            inline bool getson(TreeNodeType *now)
            {
                return (now&&now->opi)?now->opi->ch[1]==now:false;
            }
            
            inline void updata(TreeNodeType *now)
            {
                now->size=now->w;
                if(now->ch[0]) now->size+=now->ch[0]->size;
                if(now->ch[1]) now->size+=now->ch[1]->size;
            }
            
            inline void rotate(TreeNodeType *now)
            {
                bool pos=getson(now);
                TreeNodeType *opi=now->opi,*fopi=opi->opi;
                opi->ch[pos]=now->ch[pos^1];
                if(opi->ch[pos]) opi->ch[pos]->opi=opi;
                if(fopi) fopi->ch[getson(opi)]=now;
                now->ch[pos^1]=opi,opi->opi=now,now->opi=fopi;
                updata(opi),updata(now);
            }
            
            inline void splay(TreeNodeType *now)
            {
                for(TreeNodeType *opi;opi=now->opi;rotate(now))
                {
                    if(opi->opi) rotate(getson(now)==getson(opi)?opi:now);
                }
                root=now;
            }
            
        public:
            int l,r,mid,size;
            
            TreeNodeType *root;
            
            SegmentTreeNodeType()
            {
                root=NULL;
            }
            
            void insert(int x)
            {
                if(!root)
                {
                    root=new TreeNodeType;
                    root->key=x,root->size=1,root->w=1;
                    return ;
                }
                TreeNodeType *now=root,*opi=NULL;
                while(1)
                {
                    if(x==now->key)
                    {
                        now->w++,now->size++,splay(now);
                        return ;
                    }
                    opi=now;
                    if(x<now->key) now=now->ch[0];
                    else now=now->ch[1];
                    if(!now)
                    {
                        now=opi->ch[x>opi->key]=new TreeNodeType;
                        now->key=x,now->w=1,now->size=1,now->opi=opi,splay(now);
                        return ;
                    }
                }
            }
            
            void find(int x)
            {
                TreeNodeType *now=root;
                while(1)
                {
                    if(!now) return ;
                    if(now->key==x)
                    {
                        splay(now);
                        return ;
                    }
                    if(x<now->key) now=now->ch[0];
                    else now=now->ch[1];
                }
            }
            
            void del()
            {
                if(root->w>1)
                {
                    root->w--,root->size--;
                    return ;
                }
                if(!root->ch[0]&&!root->ch[1])
                {
                    if(root) delete root;
                    root=NULL;
                    return ;
                }
                if(root->ch[0]&&root->ch[1])
                {
                    TreeNodeType *now=root->ch[0];
                    while(now->ch[1]) now=now->ch[1];
                    now->ch[1]=root->ch[1],now->ch[1]->opi=now;
                    root=root->ch[0];if(root->opi) delete root->opi;
                    root->opi=NULL,splay(now->ch[1]);
                    return ;
                }
                if(root->ch[0])
                {
                    root=root->ch[0];if(root->opi) delete root->opi;
                    root->opi=NULL;
                }
                if(root->ch[1])
                {
                    root=root->ch[1];if(root->opi) delete root->opi;
                    root->opi=NULL;
                }
            }
    };
    class SegmentTreeNodeType tree[maxn<<2];
    
    int n,m,ai[maxn],use[maxn],p,size;
    
    inline void in(int &now)
    {
        char Cget=getchar();now=0;
        while(Cget>'9'||Cget<'0') Cget=getchar();
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
    }
    
    void tree_build(int now,int l,int r)
    {
        tree[now].l=l,tree[now].r=r,tree[now].size=r-l+1;
        for(int i=l;i<=r;i++) tree[now].insert(ai[i]);
        if(l==r) return ;
        tree[now].mid=l+r>>1;
        tree_build(now<<1,l,tree[now].mid);
        tree_build(now<<1|1,tree[now].mid+1,r);
    }
    
    void tree_query(int now,int l,int r)
    {
        if(tree[now].l==l&&tree[now].r==r)
        {
            if(tree[now].root) use[++p]=now,size+=tree[now].root->size;
            return ;
        }
        if(r<=tree[now].mid) tree_query(now<<1,l,r);
        else if(l>tree[now].mid) tree_query(now<<1|1,l,r);
        else tree_query(now<<1,l,tree[now].mid),tree_query(now<<1|1,tree[now].mid+1,r);
    }
    
    void tree_change(int now,int to,int x)
    {
        tree[now].find(ai[to]),tree[now].del(),tree[now].insert(x);
        if(tree[now].l==tree[now].r) return ;
        if(to<=tree[now].mid) tree_change(now<<1,to,x);
        else tree_change(now<<1|1,to,x);
    }
    
    int main()
    {
    //    freopen("operator.txt","r",stdin);
    //    freopen("output.txt","w",stdout);
        in(n),in(m);int l,r,s,k,pos,li,ri,kk,op,num;
        for(int i=1;i<=n;i++) in(ai[i]);
        tree_build(1,1,n);
        for(;m--;)
        {
            in(li),in(ri),in(s),in(k);
            size=0,p=0,tree_query(1,li,ri);
            l=1,r=n,op=((ri-li+1)>>1)+1,num=0;
            while(l<r)
            {
                int mid=l+r>>1;
                kk=0;
                for(int i=1;i<=p;i++)
                {
                    if(!use[i]) continue;
                    tree[use[i]].insert(mid);
                    kk+=tree[use[i]].root->size-1;
                    if(tree[use[i]].root->ch[1]) kk-=tree[use[i]].root->ch[1]->size;
                    tree[use[i]].del();
                }
                kk-=num;
                if(kk>=op) r=mid,pos=l,size=kk;
                else if(size-kk>=op) l=mid+1,num+=kk,pos=l,size-=kk;
                else
                {
                    pos=-1;
                    break;
                }
            }
            printf("%d
    ",pos==-1?s:pos);
            if(pos!=-1) s=l;
            for(;k--;) in(pos),tree_change(1,pos,s),ai[pos]=s;
        }
        size=0,p=0,tree_query(1,1,n);
        l=1,r=n,op=(n>>1)+1,num=0;
        while(l<r)
        {
            int mid=l+r>>1;
            kk=0;
            for(int i=1;i<=p;i++)
            {
                if(!use[i]) continue;
                tree[use[i]].insert(mid);
                kk+=tree[use[i]].root->size-1;
                if(tree[use[i]].root->ch[1]) kk-=tree[use[i]].root->ch[1]->size;
                tree[use[i]].del();
            }
            kk-=num;
            if(kk>=op) r=mid,pos=l,size=kk;
            else if(size-kk>=op) l=mid+1,num+=kk,pos=l,size-=kk;
            else
            {
                pos=-1;
                break;
            }
        }
        printf("%d
    ",pos);
        return 0;
    }
  • 相关阅读:
    JAVA 正则表达式 (超详细)
    Windows命令-route
    Spring3 MVC请求参数获取的几种方法[转]
    Linux-支持中文
    Linux-Tmux使用初体验
    Linux命令-工作管理命令:&,ctrl+z,jobs,fg,bg
    Linux命令-服务管理命令:chkconfig
    Linux命令-文件系统常用命令:df,du,fsck,dumpe2fs
    Linux命令-用户管理:useradd,userdel,usermod,id,su,env,exit
    Linux命令-某个用户组下面的所有用户
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6826082.html
Copyright © 2011-2022 走看看