zoukankan      html  css  js  c++  java
  • 平衡树

    新学了无旋 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;
    }
  • 相关阅读:
    (转)介绍一些.net开源项目
    (转).Net有哪些大型项目、大型网站的案例?
    Linux下的awk使用
    linux下的sed使用
    linux下的find、grep、cut使用
    CentOS7下的Zabbix4.4安装配置
    NetBackup linux客户端安装
    bat小脚本
    批量复制指定目录下的文件,并统计执行时间
    iptables
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/11756540.html
Copyright © 2011-2022 走看看