树套树

Posted tuchen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树套树相关的知识,希望对你有一定的参考价值。

历时三天终于打过了树套树  激动激动激动

写个博客纪念一下  

二逼平衡树~

// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 101000;
const int INF = 1e9+7;

int n,m,tot;
int a[maxn],b[maxn];
int rt[maxn];

struct Node{
    int ch[2];
    int v,fa;
    int sz,cnt;
    
    void init(int val,int f){
        ch[0]=ch[1]=0;
        v=val,fa=f;
        sz=cnt=1;
    }
}t[maxn*100];

void pushup(int i){ t[i].sz=t[t[i].ch[0]].sz+t[t[i].ch[1]].sz+t[i].cnt; }

void rotate(int x){
    int y=t[x].fa,z=t[y].fa;
    int k=(t[y].ch[1]==x);
    t[z].ch[t[z].ch[1]==y]=x;
    t[x].fa=z;
    t[y].ch[k]=t[x].ch[k^1];
    t[t[x].ch[k^1]].fa=y;
    t[x].ch[k^1]=y;
    t[y].fa=x;
    pushup(y); pushup(x);
}

void splay(int x,int g,int ts){
    while(t[x].fa!=g){
        int y=t[x].fa,z=t[y].fa;
        if(z!=g){
            (t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
        }
        rotate(x);
    }
    if(g==0) rt[ts]=x;
}

void insert(int ts,int k){
    int u=rt[ts],ff=0;
    if(!u){
        rt[ts]=u=++tot;
        t[u].init(k,0);
        return;
    } 
    while(u&&t[u].v!=k) ff=u,u=t[u].ch[k>t[u].v];
    if(u) ++t[u].cnt;
    else{
        u=++tot;
        if(ff!=0) t[ff].ch[k>t[ff].v]=u;
        t[u].init(k,ff);
    }
    splay(u,0,ts);
}

void find(int ts,int x){
    int u=rt[ts];
    if(!u) return;
    while(t[u].ch[x>t[u].v]&&t[u].v!=x){
        u=t[u].ch[x>t[u].v]; 
    }
    splay(u,0,ts); 
}

int nxt(int ts,int x,int c){
    find(ts,x);
    int u=rt[ts];
    if(t[u].v>x && c) return u;
    if(t[u].v<x && !c) return u;
    u=t[u].ch[c];
    while(t[u].ch[c^1]){
        u=t[u].ch[c^1];
    }return u;
}

void del(int ts,int x){
    int pre=nxt(ts,x,0);
    int nx=nxt(ts,x,1);
    splay(pre,0,ts);splay(nx,pre,ts);
    int d=t[nx].ch[0];
    if(t[d].cnt>1){
        --t[d].cnt;
        splay(d,0,ts);
    }else{
        t[nx].ch[0]=0;
    }
}

int rk(int ts,int x){
    find(ts,x);
    int u=rt[ts];
    return t[t[u].ch[0]].sz;
}

void build(int i,int l,int r){
    for(int j=l;j<=r;j++) insert(i,a[j]);
    insert(i,-2147483647); insert(i,2147483647);
    if(l==r){ return; }
    int mid=(l+r)/2;
    build(i<<1,l,mid),build(i<<1|1,mid+1,r);
}

void update(int i,int pos,int k,int l,int r,int o){
    del(i,o);
    insert(i,k);
    if(l==r){ return; }
    int mid=(l+r)/2;
    if(pos<=mid) update(i<<1,pos,k,l,mid,o);
    else update(i<<1|1,pos,k,mid+1,r,o);
}

int qry_rk(int i,int l,int r,int k,int x,int y){
    if(x<=l && r<=y){
        insert(i,k);
        int p=rk(i,k)-1;
        del(i,k);
        return p;
    }
    int mid=(l+r)/2,res=0;
    if(x<=mid) res+=qry_rk(i<<1,l,mid,k,x,y);
    if(y>mid) res+=qry_rk(i<<1|1,mid+1,r,k,x,y);
    return res;
}

int qry_pre(int i,int l,int r,int k,int x,int y){
    if(x<=l && r<=y){
        insert(i,k);
        int u=nxt(i,k,0);
        del(i,k);
        return t[u].v;
    }
    int mid=(l+r)/2;
    int res=-2147483647;
    if(x<=mid) res=max(res,qry_pre(i<<1,l,mid,k,x,y));
    if(y>mid) res=max(res,qry_pre(i<<1|1,mid+1,r,k,x,y));
    return res;
}

int qry_nxt(int i,int l,int r,int k,int x,int y){
    if(x<=l && r<=y){
        insert(i,k);
        int u=nxt(i,k,1);
        del(i,k); 
        return t[u].v;
    }
    int mid=(l+r)/2;
    int res=2147483647;
    if(x<=mid) res=min(res,qry_nxt(i<<1,l,mid,k,x,y));
    if(y>mid) res=min(res,qry_nxt(i<<1|1,mid+1,r,k,x,y));
    return res;
}

int qry_nx(int i,int l,int r,int k,int x,int y,int c){
    if(x<=l && r<=y){
        return t[nxt(i,k,c)].v;
    }
    int mid=(l+r)/2;
    if(c==0){
        int res=-INF;
        if(x<=mid) return max(res,qry_nx(i<<1,l,mid,k,x,y,c));
        if(y>mid) return max(res,qry_nx(i<<1|1,mid+1,r,k,x,y,c));
    }else{
        int res=INF;
        if(x<=mid) return min(res,qry_nx(i<<1,l,mid,k,x,y,c));
        if(y>mid) return min(res,qry_nx(i<<1|1,mid+1,r,k,x,y,c));
    }
}

void print(int i){
    if(!i) return;
    print(t[i].ch[0]);
    printf("%d ",t[i].v);
    print(t[i].ch[1]);
}

void write(int i,int l,int r){
    if(l==r){
        printf("%d : %d
",rt[i],t[rt[i]].v);
        return;
    }
    printf("%d :",rt[i]);
    print(rt[i]);
    printf("
");
    int mid=(l+r)/2;
    write(i<<1,l,mid),write(i<<1|1,mid+1,r);
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<0 || ch>9){ if(ch==-) f=-1; ch=getchar(); } while(ch>=0 && ch<=9){ s=s*10+ch-0; ch=getchar(); } return s*f; }

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    build(1,1,n);
//    write(1,1,n);
    int op,l,r,x;
    for(int i=1;i<=m;i++){
        op=read(),l=read(),r=read();
        if(op==1){
            x=read();
            printf("%d
",qry_rk(1,1,n,x,l,r)+1); 
        }else if(op==2){
            x=read();
            int L=0,R=1e8,ans=0,mid;
            while(L<=R){
                mid=(L+R)/2;
                if(qry_rk(1,1,n,mid,l,r)<x){
                    L=mid+1;
                }else{
                    ans=mid;
                    R=mid-1;
                }
            }
            printf("%d
",ans-1);
        }else if(op==3){
            update(1,l,r,1,n,a[l]);
            a[l]=r;
        }else if(op==4){
            x=read();
            printf("%d
",qry_pre(1,1,n,x,l,r)); 
        }else if(op==5){
            x=read();
            printf("%d
",qry_nxt(1,1,n,x,l,r)); 
        }
    }
    return 0;
}

 

以上是关于树套树的主要内容,如果未能解决你的问题,请参考以下文章

「模板」 树套树

树套树三题 题解

模板二逼平衡树(树套树)

P3380 模板二逼平衡树(树套树)

[BZOJ 720][JZYZOJ 2016]gty的妹子树 强制在线 树分块/树套树

树套树-线段树套平衡树