树套树代码

树状数组套线段树:

#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;
}
原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6826082.html