zoukankan      html  css  js  c++  java
  • Treap 模板

    感觉平衡树也没有以前想的那么玄乎,(其实set超好用的),非旋式Treap挺好理解,和可并堆,二叉搜索树有很大联系

    推荐博客:http://memphis.is-programmer.com/posts/46317.html

    模板也是摘自这位dalao的

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 2000005
    #define rep(i,x,y) for(int i=x;i<=y;++i)
    #define dep(i,x,y) for(int i=x;i>=y;--i)
    
    struct Treap{
        Treap *l,*r;
        int fix,key,size;
        Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(1){}
        
        inline void updata(){
            size=1+(l?l->size:0)+(r?r->size:0);
        }
    }*root;
    typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 
    
    inline int Size(Treap *x){return x?x->size:0;}//这样求size可以防止访问空指针 
    
    Treap *Merge(Treap *A,Treap *B){//合并操作 
        if(!A)return B;
        if(!B)return A;
        if(A->fix<B->fix){
            A->r=Merge(A->r,B);
            A->updata();
            return A;
        }
        else{
            B->l=Merge(A,B->l);
            B->updata();
            return B;
        }
    }
    
    Droot Split(Treap *x,int k){//拆分操作 
        if(!x)return Droot(NULL,NULL);
        Droot y;
        if(Size(x->l)>=k){
            y=Split(x->l,k);
            x->l=y.second;
            x->updata();
            y.second=x;
        }
        else{
            y=Split(x->r,k-Size(x->l)-1);
            x->r=y.first;
            x->updata();
            y.first=x;
        }
        return y;
    }
    
    Treap *Build(int *a){//建造操作 
        static Treap *stack[maxn],*x,*last;
        int p=0;
        rep(i,1,a[0]){
            x=new Treap(a[i]);
            last=NULL;
            while(p && stack[p]->fix>x->fix){
                stack[p]->updata();
                last=stack[p];
                stack[p--]=NULL;
            }
            if(p) stack[p]->r=x;
            x->l=last;
            stack[++p]=x;
        }
        while(p) stack[p--]->updata();
        return stack[1];
    }
    
    int Findkth(int k){//查找第K小 
        Droot x=Split(root,k-1);
        Droot y=Split(x.second,1);
        Treap *ans=y.first;
        root=Merge(Merge(x.first,ans),y.second);
        return ans->key;
    }
    
    int Getkth(Treap *x,int v){//询问一个数是第几大 
        if(!x)return 0;
        return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+1;
    }
    
    void Insert(int v){//插入操作 
        int k=Getkth(root,v);
        Droot x=Split(root,k);
        Treap *n=new Treap(v);
        root=Merge(Merge(x.first,n),x.second);
    }
    
    void Delete(int k){//删除操作 
        Droot x=Split(root,k-1);
        Droot y=Split(x.second,1);
        root=Merge(x.first,y.second);
    }
    
    int a[maxn],M,x,y;
    
    int main(){
        scanf("%d",a);
        rep(i,1,a[0]) scanf("%d",a+i);
        sort(a+1,a+1+a[0]);
        root=Build(a);
        scanf("%d",&M);
        while(M--){
            char ch=getchar();
            while(ch!='Q' && ch!='A' && ch!='D') ch=getchar();
            scanf("%d",&x);
            if(ch=='Q') printf("%d
    ",Findkth(x));
            if(ch=='A') Insert(x);
            if(ch=='D') Delete(x);
        }
    } 
    View Code

    改了一下之后就A了文艺平衡树

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 2000005
    #define rep(i,x,y) for(int i=x;i<=y;++i)
    #define dep(i,x,y) for(int i=x;i>=y;--i)
    int n;
    struct Treap{
        Treap *l,*r;
        int fix,key,size;
        bool fg;
        Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(1){}
        
        inline void updata(){
            size=1+(l?l->size:0)+(r?r->size:0);
        }
    }*root;
    typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 
    
    inline int Size(Treap *x){return x?x->size:0;}//这样求size可以防止访问空指针 
    void pushdown(Treap *x){
        if(!x->fg)return;
        x->fg=0;
        swap(x->l,x->r);
        if( x->l ) x->l->fg^=1;
        if( x->r ) x->r->fg^=1;
    }
    Treap *Merge(Treap *A,Treap *B){//合并操作 
        if(!A)return B;
        if(!B)return A;
        pushdown(A);pushdown(B);
        if(A->fix<B->fix){
            A->r=Merge(A->r,B);
            A->updata();
            return A;
        }
        else{
            B->l=Merge(A,B->l);
            B->updata();
            return B;
        }
    }
    
    Droot Split(Treap *x,int k){//拆分操作 
        if(!x)return Droot(NULL,NULL);
        Droot y;
        pushdown(x);
        if(Size(x->l)>=k){
            y=Split(x->l,k);
            x->l=y.second;
            x->updata();
            y.second=x;
        }
        else{
            y=Split(x->r,k-Size(x->l)-1);
            x->r=y.first;
            x->updata();
            y.first=x;
        }
        return y;
    }
    Treap *build(int L,int R){
        if(L>R)return NULL;
        int mid=(L+R)>>1,key=mid-1;
        Treap *x =new Treap(key);
        x->l = build(L,mid-1);
        x->r = build(mid+1,R);
        x->updata();
        return x;
    }
    Treap *Build(int *a){//建造操作 
        static Treap *stack[maxn],*x,*last;
        int p=0;
        rep(i,1,a[0]){
            x=new Treap(a[i]);
            last=NULL;
            while(p && stack[p]->fix>x->fix){
                stack[p]->updata();
                last=stack[p];
                stack[p--]=NULL;
            }
            if(p) stack[p]->r=x;
            x->l=last;
            stack[++p]=x;
        }
        while(p) stack[p--]->updata();
        return stack[1];
    }
    
    void order(Treap *x){
        if( x == NULL ) return;
        pushdown(x);
        order(x->l);
        if(x->key >= 1 && x->key<=n)printf("%d ",x->key);
        order(x->r);
    }
    void rev(int L,int R){
        Droot tmp1=Split(root,R+1);
        Droot tmp2=Split(tmp1.first,L);
        tmp2.second->fg^=1;
        root = NULL;
        root = Merge(tmp2.first,tmp2.second);
        root = Merge(root,tmp1.second);
    }
    //int Findkth(int k){//查找第K小 
    //    Droot x=Split(root,k-1);
    //    Droot y=Split(x.second,1);
    //    Treap *ans=y.first;
    //    root=Merge(Merge(x.first,ans),y.second);
    //    return ans->key;
    //}
    
    //int Getkth(Treap *x,int v){//询问一个数是第几大 
    //    if(!x)return 0;
    //    return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+1;
    //}
    
    //void Insert(int v){//插入操作 
    //    int k=Getkth(root,v);
    //    Droot x=Split(root,k);
    //    Treap *n=new Treap(v);
    //    root=Merge(Merge(x.first,n),x.second);
    //}
    
    //void Delete(int k){//删除操作 
    //    Droot x=Split(root,k-1);
    //    Droot y=Split(x.second,1);
    //    root=Merge(x.first,y.second);
    //}
    
    //int a[maxn],M,x,y;
    int M;
    int main(){
        //scanf("%d",a);
        //rep(i,1,a[0]) scanf("%d",a+i);
        //sort(a+1,a+1+a[0]);
        //root=Build(a);
        scanf("%d",&n);
        scanf("%d",&M);
        root=build(1,n+2);
        int L,R;
        while(M--){
    //        char ch=getchar();
    //        while(ch!='Q' && ch!='A' && ch!='D') ch=getchar();
    //        scanf("%d",&x);
    //        if(ch=='Q') printf("%d
    ",Findkth(x));
    //        if(ch=='A') Insert(x);
    //        if(ch=='D') Delete(x);
            scanf("%d%d",&L,&R);
            rev(L,R);
        }
        order(root);
    } 
    View Code

    再粘一个非指针版的我敬爱的学长szb写的,浙大一本爷

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    #define mp make_pair
    typedef pair<int,int> par;
    const int N=100010;
    const int inf=1e9;
    int n,root,cnt;
    int l[N],r[N],key[N],rnd[N],size[N];
    int readin() {
        int x=0,f=1; char ch=getchar();
        while(ch>'9'||ch<'0') {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void update(int x) {
        size[x]=size[l[x]]+size[r[x]]+1;
        return;
    }
    int merge(int x,int y) {
        if (!x||!y)
            return x+y;
        if (rnd[x]<rnd[y]) {
            r[x]=merge(r[x],y);
            update(x); return x;
        }
        else {
            l[y]=merge(x,l[y]);
            update(y); return y;
        }
    }
    par split(int x,int k) {
        if (k==0)
            return mp(0,x);
        int ls=l[x],rs=r[x];
        if (k<=size[l[x]]) {
            par t=split(l[x],k);
            l[x]=t.second; update(x);
            return mp(t.first,x);
        }
        else if (k==size[l[x]]+1) {
            r[x]=0; update(x);
            return mp(x,rs);
        }
        else {
            par t=split(rs,k-(size[l[x]]+1));
            r[x]=t.first; update(x);
            return mp(x,t.second);
        }
    }
    int query_rank(int x,int k) {
        int ans=0,t=inf;
        while(x) {
            if (k==key[x]) t=min(t,ans+size[l[x]]+1);
            if (k>key[x]) ans+=(size[l[x]]+1),x=r[x];
            else x=l[x];
        }
        return t==inf?ans:t;
    }
    void insert(int x) {
        int k=query_rank(root,x);
        par t=split(root,k);
        key[++cnt]=x,rnd[cnt]=rand(),size[cnt]=1;
        root=merge(t.first,cnt);
        root=merge(root,t.second);
        return;
    }
    void del(int x) {
        int k=query_rank(root,x);
        par t1=split(root,k);
        par t2=split(t1.first,k-1);
        root=merge(t2.first,t1.second);
        return;
    }
    int query_num(int x,int k) {
        while(1) {
            if (k==size[l[x]]+1) return key[x];
            if (k<=size[l[x]]) x=l[x];
            else k-=(size[l[x]]+1),x=r[x];
        }
    }
    int query_pre(int x,int k) {
        int ans=-inf;
        while(x) {
            if (key[x]<k)
                ans=max(ans,key[x]),x=r[x];
            else
                x=l[x];
        }
        return ans;
    }
    int query_sub(int x,int k) {
        int ans=inf;
        while(x) {
            if (key[x]>k)
                ans=min(ans,key[x]),x=l[x];
            else
                x=r[x];
        }
        return ans;
    }
    int main() {
        int opt,x;
        n=readin();
        for (int i=1;i<=n;i++) {
            opt=readin(),x=readin();
            if (opt==1) insert(x);
            else if (opt==2) del(x);
            else if (opt==3) printf("%d
    ",query_rank(root,x));
            else if (opt==4) printf("%d
    ",query_num(root,x));
            else if (opt==5) printf("%d
    ",query_pre(root,x));
            else printf("%d
    ",query_sub(root,x));
        }
        return 0;
    }
    View Code

    序列终结者 ,调了好久发现区间截取错了那我咋A的文艺平衡树啊???啊~好像是那个程序建树的时候整个往后串了一位

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 2000005
    int n;
    #define inf 1000000000
    struct Treap{
        Treap *l,*r;
        int fix,key,size,mx,add;
        bool fg;
        Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(1),mx(0),fg(0),add(0){}
        void addv(int w){mx+=w;add+=w;key+=w;}
        inline void updata(){
            size=1+(l?l->size:0)+(r?r->size:0);
            mx=max(key,max((l?l->mx:-inf),(r?r->mx:-inf)));
        }
    }*root;
    typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 
    
    inline int Size(Treap *x){return x?x->size:0;}//这样求size可以防止访问空指针 
    void pushdown(Treap *x){
        if(x->fg){
        x->fg=0;
        swap(x->l,x->r);
        if( x->l ) x->l->fg^=1;
        if( x->r ) x->r->fg^=1;}
        if(x->add){
            if( x->l ) x->l->addv(x->add);
            if( x->r ) x->r->addv(x->add);
            x->add=0;
        }
    }
    Treap *Merge(Treap *A,Treap *B){//合并操作 
        if(!A)return B;
        if(!B)return A;
        pushdown(A);pushdown(B);
        if(A->fix<B->fix){
            A->r=Merge(A->r,B);
            A->updata();
            return A;
        }
        else{
            B->l=Merge(A,B->l);
            B->updata();
            return B;
        }
    }
    
    Droot Split(Treap *x,int k){//拆分操作 
        if(!x)return Droot(NULL,NULL);
        Droot y;
        pushdown(x);
        if(Size(x->l)>=k){
            y=Split(x->l,k);
            x->l=y.second;
            x->updata();
            y.second=x;
        }
        else{
            y=Split(x->r,k-Size(x->l)-1);
            x->r=y.first;
            x->updata();
            y.first=x;
        }
        return y;
    }
    
    void rev(int L,int R){
        Droot tmp1=Split(root,R);
        Droot tmp2=Split(tmp1.first,L-1);
        tmp2.second->fg^=1;
        root = Merge( Merge(tmp2.first,tmp2.second),tmp1.second);
    }
    void up(int L,int R,int v){
        Droot tmp1=Split(root,R);
        Droot tmp2=Split(tmp1.first,L-1);
        tmp2.second->addv(v);
        root = Merge(Merge(tmp2.first,tmp2.second),tmp1.second);
    }
    int query(int L,int R){
        Droot tmp1=Split(root,R);
        Droot tmp2=Split(tmp1.first,L-1);
        int ret=tmp2.second->mx;
        root = Merge(Merge(tmp2.first,tmp2.second),tmp1.second);
        return ret;
    }
    int M;
    int main(){
        scanf("%d",&n);
        scanf("%d",&M);
        for(int i=1;i<=n;i++){
            Treap *a=new Treap(0);
            root=Merge(root,a);
        }
        int L,R;
        int f,v;
        while(M--){
            scanf("%d",&f);
            if(f==1){
            
            scanf("%d%d%d",&L,&R,&v);
            up(L,R,v);}
            else if(f==2){
                scanf("%d%d",&L,&R); rev(L,R);
            }
            else {
                scanf("%d%d",&L,&R);
                printf("%d
    ",query(L,R));
            }
        }
        
    }
    View Code
  • 相关阅读:
    C#打开SDE数据库的几种方式
    关于DataGridView
    细说Sql Server中的视图(下)转载
    细说Sql Server中的视图(上)转载
    细说Sql Server中的视图
    Ajax实现原理,代码封装
    无限级下拉菜单(树形菜单,二级菜单)
    无限循环轮播图之JS部分(原生JS)
    无限循环轮播图之结构布局(原生JS)
    无限循环轮播图之运动框架(原生JS)
  • 原文地址:https://www.cnblogs.com/Amphetamine/p/7473933.html
Copyright © 2011-2022 走看看