平衡树

新学了无旋 treap,感觉特别好用,贴个模板在这里,之后再来补一下理解和注释。

模板题

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAXN 100010
using namespace std;
int n;

struct FhqTree{
    int L[MAXN],R[MAXN],val[MAXN],key[MAXN],siz[MAXN];
    int cnt,root;
    
    int newnode(int data){
        val[++cnt]=data;
        key[cnt]=rand();
        siz[cnt]=1;
        return cnt;
    }

    void update(int now){
        siz[now]=siz[L[now]]+siz[R[now]]+1;
    }

    void split(int now,int data,int &x,int &y){
        if(!now) x=y=0;
        else{
            if(val[now]<=data){
                x=now;
                split(R[now],data,R[now],y);
            } 
            else{
                y=now;
                split(L[now],data,x,L[now]);
            }
            update(now);
        }
    }

    int merge(int x,int y){
        if(!x||!y) return x+y;
        if(key[x]>key[y]){
            R[x]=merge(R[x],y);
            update(x);
            return x;
        }
        else{
            L[y]=merge(x,L[y]);
            update(y);
            return y;
        }
    }

    int x,y,z;

    void insert(int data){
        split(root,data,x,y);
        root=merge(merge(x,newnode(data)),y);
    }

    void erease(int data){
        split(root,data,x,z);
        split(x,data-1,x,y);
        y=merge(L[y],R[y]);
        root=merge(merge(x,y),z);
    }

    void getrank(int data){
        split(root,data-1,x,y);
        printf("%d
",siz[x]+1);
        root=merge(x,y);
    }

    void getnum(int rank){
        int now=root;
        while(now){
            if(siz[L[now]]+1==rank) break;
            else if(siz[L[now]]>=rank) now=L[now];
            else rank-=siz[L[now]]+1,now=R[now];
        }
        printf("%d
",val[now]);
    }

    void pre(int data){
        split(root,data-1,x,y);
        int now=x;
        while(R[now]) now=R[now];
        printf("%d
",val[now]);
        root=merge(x,y);
    }

    void nxt(int data){
        split(root,data,x,y);
        int now=y;
        while(L[now]) now=L[now];
        printf("%d
",val[now]);
        root=merge(x,y);
    }
}fhq;

int main(){
    srand(time(0));
    scanf("%d",&n);
    int opt,x;
    while(n--){
        scanf("%d%d",&opt,&x);
        if(opt==1) fhq.insert(x);
        else if(opt==2) fhq.erease(x);
        else if(opt==3) fhq.getrank(x);
        else if(opt==4) fhq.getnum(x);
        else if(opt==5) fhq.pre(x);
        else if(opt==6) fhq.nxt(x);
    }
    return 0;
}

当然也可以用 FhqTreap 解决区间问题, 也就是说可以完成线段数的任务, 虽然会比线段树慢一点, 但也可以做线段树做不到的区间插入

例子

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAXN 200010
using namespace std;
typedef long long LL;
int n,m;

struct FhqTreap{
    int L[MAXN],R[MAXN],siz[MAXN],key[MAXN];
    LL sum[MAXN],val[MAXN],tag[MAXN];
    int cnt,root;

    int newnode(int value){
        siz[++cnt]=1;key[cnt]=rand();
        sum[cnt]=value;val[cnt]=value;
        return cnt;
    }

    void pushdown(int id){
        sum[L[id]]+=tag[id]*siz[L[id]];
        sum[R[id]]+=tag[id]*siz[R[id]];
        val[L[id]]+=tag[id];tag[L[id]]+=tag[id];
        val[R[id]]+=tag[id];tag[R[id]]+=tag[id];
        tag[id]=0;
    }

    void pushup(int id){
        siz[id]=siz[L[id]]+siz[R[id]]+1;
        sum[id]=sum[L[id]]+sum[R[id]]+val[id];
    }

    void split(int id,int size,int &x,int &y){
        if(!id) x=y=0;
        else{
            if(tag[id]) pushdown(id);
            if(siz[L[id]]<size){
                x=id;
                split(R[id],size-siz[L[id]]-1,R[id],y);
            }
            else{
                y=id;
                split(L[id],size,x,L[id]);
            }
            pushup(id);
        }
    }

    int merge(int x,int y){
        if(!x||!y) return x+y;
        if(key[x]>key[y]){
             if(tag[x]) pushdown(x);
             R[x]=merge(R[x],y);
             pushup(x);
             return x;
        }
        else{
            if(tag[y]) pushdown(y);
            L[y]=merge(x,L[y]);
            pushup(y);
            return y;
        }
    }

    void add(int l,int r,LL value){
        int x,y,z;
        split(root,l-1,x,y);
        split(y,r-l+1,y,z);
        sum[y]+=value*siz[y];
        val[y]+=value;
        tag[y]+=value;
        root=merge(merge(x,y),z);
    }

    void insert(int pos,int value){
        int x,y;
        split(root,pos-1,x,y);
        root=merge(merge(x,newnode(value)),y);
    }

    void ask(int l,int r){
        int x,y,z;
        split(root,l-1,x,y);
        split(y,r-l+1,y,z);
        printf("%lld
",sum[y]);
        root=merge(merge(x,y),z);
    }
}fhq;

int main(){
    srand(time(0));
    scanf("%d",&n);
    for(int i=1,x;i<=n;i++){
        scanf("%d",&x);
        fhq.insert(i,x);
    }
    scanf("%d",&m);
    for(int i=1,opt,x,y,z;i<=m;i++){
        scanf("%d",&opt);
        if(opt==1){
            scanf("%d",&x);
            fhq.insert(x,0);
        }
        else if(opt==2){
            scanf("%d%d%d",&x,&y,&z);
            fhq.add(x,y,z);
        }
        else if(opt==3){
            scanf("%d%d",&x,&y);
            fhq.ask(x,y);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/BakaCirno/p/11756540.html