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

#include<cstdio>
#include<cstring>
#include<string>
#define int long long
#define WR WinterRain
#define Combo void//RIP
using namespace std;
const int WR=10010000,INF=2147483647;
int n,m;
int a[WR];
struct Treap_Tree{
    struct BalanceTree{
        int val,sze,rnk,ch[2],cnt;
    }tree[WR];
    int tot=0,root=1;
    Combo pushup(int k){
        tree[k].sze=tree[tree[k].ch[0]].sze+tree[tree[k].ch[1]].sze+tree[k].cnt;
    }
    int add_point(int v){
        tree[++tot].val=v;
        tree[tot].rnk=rand();
        tree[tot].sze=tree[tot].cnt=1;
        tree[tot].ch[0]=tree[tot].ch[1]=0;
        return tot;
    }
    Combo rotat(int &id,int dir){
        int tmp=tree[id].ch[dir^1];
        tree[id].ch[dir^1]=tree[tmp].ch[dir];
        tree[tmp].ch[dir]=id;
        id=tmp;
        pushup(tree[id].ch[dir]),pushup(id);
    }
    Combo insrt(int &id,int v){
        if(!id){
            id=add_point(v);
            return;
        }
        if(v==tree[id].val) tree[id].cnt++;
        else{
            int dir;
            if(v<tree[id].val) dir=0;
            else dir=1;
            insrt(tree[id].ch[dir],v);
            if(tree[id].rnk<tree[tree[id].ch[dir]].rnk) rotat(id,dir^1);
        }
        pushup(id);
    }
    Combo remov(int &id,int v){
        if(!id) return;
        if(v==tree[id].val){
            if(tree[id].cnt>1){
                tree[id].cnt--;
                pushup(id);
                return;
            }
            if(tree[id].ch[0]||tree[id].ch[1]){
                if(!tree[id].ch[1]||tree[tree[id].ch[0]].rnk>tree[tree[id].ch[1]].rnk){
                    rotat(id,1);remov(tree[id].ch[1],v);
                }else{
                    rotat(id,0);remov(tree[id].ch[0],v);
                }
                pushup(id);
                return;
            }
            id=0;return;
        }
        if(v<tree[id].val) remov(tree[id].ch[0],v);
        else remov(tree[id].ch[1],v);
        pushup(id);
    }
    int get_rank(int id,int v){
        if(!id) return 0;
        //printf("%d %d\n",id,v);
        if(v==tree[id].val) return tree[tree[id].ch[0]].sze;
        if(v<tree[id].val) return get_rank(tree[id].ch[0],v);
        else return get_rank(tree[id].ch[1],v)+tree[id].cnt+tree[tree[id].ch[0]].sze;
    }
    int get_val(int id,int rk){
        if(!id) return INF;
        if(rk<=tree[tree[id].ch[0]].sze) return get_val(tree[id].ch[0],rk);
        else if(rk<=tree[id].cnt+tree[tree[id].ch[0]].sze) return tree[id].val;
        else return get_val(tree[id].ch[1],rk-tree[tree[id].ch[0]].sze-tree[id].cnt);
    }
    int get_pre(int id,int v){
        int pre=-INF;
        while(id){
            if(tree[id].val<v) pre=tree[id].val,id=tree[id].ch[1];
            else id=tree[id].ch[0];
        }
        return pre;
    }
    int get_nxt(int id,int v){
        int nxt=INF;
        while(id){
            if(tree[id].val>v) nxt=tree[id].val,id=tree[id].ch[0];
            else id=tree[id].ch[1];
        }
        //printf("%d\n\n",nxt);
        return nxt;
    }
}treap;
struct Segment_Tree{
    struct SegmentTree{
        int l,r,root;
    }tree[WR];
    Combo build(int k,int l,int r){
        tree[k].l=l,tree[k].r=r;
        for(int i=l;i<=r;i++) treap.insrt(tree[k].root,a[i]);
        if(l==r) return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    Combo modify(int k,int pos,int v){
        treap.remov(tree[k].root,a[pos]);
        treap.insrt(tree[k].root,v);
        if(tree[k].l==tree[k].r) return;
        int mid=(tree[k].l+tree[k].r)>>1;
        if(pos<=mid) modify(k<<1,pos,v);
        else modify(k<<1|1,pos,v);
    }
    int get_rank(int k,int l,int r,int v){
        //printf("%d %d %d %d %d %d\n",k,tree[k].l,tree[k].r,l,r,tree[k].root);
        if(tree[k].l>r||tree[k].r<l) return 0;
        if(tree[k].l>=l&&tree[k].r<=r) return treap.get_rank(tree[k].root,v);
        else return get_rank(k<<1,l,r,v)+get_rank(k<<1|1,l,r,v);
    }
    int get_num(int st,int ed,int v){
        int l=0,r=1e8;
        while(l<r){
            int mid=(l+r+1)>>1;
            //printf("%d\n",get_rank(1,st,ed,mid));
            if(get_rank(1,st,ed,mid)<v) l=mid;
            else r=mid-1;
        }
        return r;
    }
    int get_pre(int k,int l,int r,int v){
        if(tree[k].l>r||tree[k].r<l) return -INF;
        if(tree[k].l>=l&&tree[k].r<=r) return treap.get_pre(tree[k].root,v);
        else return max(get_pre(k<<1,l,r,v),get_pre(k<<1|1,l,r,v));
    }
    int get_nxt(int k,int l,int r,int v){
        //printf("%d %d %d %d\n",k,tree[k].l,tree[k].r,v);
        if(tree[k].l>r||tree[k].r<l) return INF;
        if(tree[k].l>=l&&tree[k].r<=r) return treap.get_nxt(tree[k].root,v);
        else return min(get_nxt(k<<1,l,r,v),get_nxt(k<<1|1,l,r,v));
    }
}segment;
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<1)+(s<<3)+ch-48;
        ch=getchar();
    }
    return s*w;
}
signed main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    segment.build(1,1,n);
    for(int i=1;i<=m;i++){
        int opt=read();
        if(opt==1){
            int l=read(),r=read(),v=read();
            printf("%lld\n",segment.get_rank(1,l,r,v)+1);
        }
        if(opt==2){
            int l=read(),r=read(),v=read();
            printf("%lld\n",segment.get_num(l,r,v));
        }
        if(opt==3){
            int pos=read(),x=read();
            segment.modify(1,pos,x);
            a[pos]=x;
        }
        if(opt==4){
            int l=read(),r=read(),v=read();
            printf("%lld\n",segment.get_pre(1,l,r,v));
        }
        if(opt==5){
            int l=read(),r=read(),v=read();
            printf("%lld\n",segment.get_nxt(1,l,r,v));
        }
    }
    return 0;
}

 

posted @ 2022-05-15 21:01  冬天丶的雨  阅读(22)  评论(0编辑  收藏  举报
Live2D