1. 程式人生 > >【模板】bzoj-3224普通平衡樹(splay&treap&SBT)

【模板】bzoj-3224普通平衡樹(splay&treap&SBT)

先吐槽一下,要找塊好模板真不容易,畢竟大家都有各自的程式碼風格,強迫自己去看非自己風格的程式碼真是痛苦,所以在網上新增一種型別的模板

最近才發現這題A了三遍,分別是以三種平衡樹的模板題A的,所以稍微彙總一下,讓後來者有個型別的模板可以依靠

相信看模板的人都看過題解了,所以這裡就不寫題解了 本來就是模板題,哪來的題解

如果有剛學平衡樹的,奉勸一句

splay好好學,SBT慢慢學,treap仔細學

splay 版:

#include<bits/stdc++.h>
using namespace std;
#define update(x) tr[x].size=tr[tr[x].ch[0]].size+tr[tr[x].ch[1]].size+tr[x].cnt
#define cl(x) memset(x,0,sizeof(x)) #define cl1(x) memset(x,-1,sizeof(x)) #define rg register #define oo 0x3f3f3f3f template <typename _Tp> inline void read(_Tp&x){char c11=getchar();x=0;bool booo=0; while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),booo=1; while
(isdigit(c11)){x=x*10+c11-'0';c11=getchar();}if(booo)x=-x;return ; } const int N=505000; struct node{int size,f,ch[2],val,cnt;}tr[N]; int root,sz; inline int nxt(int,int); inline void find(int); inline void insert(int); inline void del(int); inline int K_th(int); inline void rotate(int x){ int fa=tr[x].f; int
grand=tr[fa].f; int le=(tr[fa].ch[1]==x); tr[grand].ch[tr[grand].ch[1]==fa]=x; tr[x].f=grand; tr[fa].ch[le]=tr[x].ch[le^1]; tr[tr[x].ch[le^1]].f=fa; tr[x].ch[le^1]=fa; tr[fa].f=x; update(fa);update(x); return ; } void splay(int x,int target){ for(rg int fa;(fa=f[x])!=target;rotate(x)) if(f[f[x]]!=target) rotate(blood(x)==blood(f[x])?f[x]:x); if(!target)root=x; return ; } int main(){ insert(-oo);insert(+oo); rg int m,opt,A;read(m); while(m--){ read(opt);read(A); switch(opt){ case 1: insert(A); break; case 2: del(A); break; case 3: find(A); printf("%d\n",tr[tr[root].ch[0]].size); break; case 4: printf("%d\n",K_th(A+1)); break; case 5: printf("%d\n",tr[nxt(A,0)].val); break; case 6: printf("%d\n",tr[nxt(A,1)].val); break; default: puts("ERROR"); return 0; } } return 0; } inline int K_th(int x){ int now=root; if(tr[now].size<x)return -1; while("KB is too powerful"){ if(x>tr[tr[now].ch[0]].size+tr[now].cnt){ x-=tr[tr[now].ch[0]].size+tr[now].cnt; now=tr[now].ch[1]; } else if(x<=tr[tr[now].ch[0]].size) now=tr[now].ch[0]; else return tr[now].val; } return -1; } inline void del(int x){ int fr=nxt(x,0),Ba=nxt(x,1); splay(fr,0);splay(Ba,fr); if(tr[tr[Ba].ch[0]].cnt>1){ --tr[tr[Ba].ch[0]].cnt; splay(tr[Ba].ch[0],0); } else tr[Ba].ch[0]=0; return ; } inline void insert(int x){ int now=root,f=0; while(now&&tr[now].val!=x){ f=now; now=tr[now].ch[x>tr[now].val]; } if(now)++tr[now].cnt; else{ now=++sz; if(f)tr[f].ch[x>tr[f].val]=now; tr[now].ch[0]=tr[now].ch[1]=0; tr[now].f=f,tr[now].val=x; tr[now].cnt=1;tr[now].size=1; } splay(now,0); return ; } inline int nxt(int x,int leaf){ find(x); int now=root; if(leaf&&tr[now].val>x)return now; if(!leaf&&tr[now].val<x)return now; now=tr[now].ch[leaf]; while(tr[now].ch[leaf^1])now=tr[now].ch[leaf^1]; return now; } inline void find(int x){ if(!root)return ; int now=root; while(tr[now].ch[x>tr[now].val]&&x!=tr[now].val)now=tr[now].ch[x>tr[now].val]; splay(now,0); return ; }

treap 版:

//bzoj3224
#include<bits/stdc++.h>
using namespace std;
#define rg register

#define update(x) size[now]=size[ch[now][0]]+size[ch[now][1]]+tot[now];

template <typename _Tp> inline void read(_Tp&x){
    char c11=getchar();x=0;bool booo=0;
    while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-'){c11=getchar();booo=1;}
    while(isdigit(c11)){x=x*10+c11-'0';c11=getchar();}if(booo)x=-x;return ;
}

const int N=100005;
int ch[N][2],data[N],rnd[N],tot[N],size[N];
int n,root,ans,sz;

inline void lturn(int &now){
    int child=ch[now][1];ch[now][1]=ch[child][0];ch[child][0]=now;
    size[child]=size[now];update(now);now=child;
    return ;
}

inline void rturn(int &now){
    int child=ch[now][0];ch[now][0]=ch[child][1];ch[child][1]=now;
    size[child]=size[now];update(now);now=child;
    return ;
}

void ins(int &now,int x){
    if(!now){
        now=++sz;
        size[now]=tot[now]=1;
        data[now]=x;rnd[now]=rand();
        return ;
    }
    ++size[now];
    if(data[now]==x){++tot[now];return ;}
    if(data[now]<x){
        ins(ch[now][1],x);
        if(rnd[ch[now][1]]<rnd[now])lturn(now);
    }
    else{
        ins(ch[now][0],x);
        if(rnd[ch[now][0]]<rnd[now])rturn(now);
    }
    return ;
}

void del(int &now,int x){
    if(!now)return ;
    if(data[now]==x){
        if(tot[now]>1){--tot[now],--size[now];return ;}
        if(!(ch[now][0]*ch[now][1])){now=ch[now][0]+ch[now][1];return ;}
        if(rnd[ch[now][0]]<rnd[ch[now][1]])
            rturn(now),del(now,x);
        else
            lturn(now),del(now,x);
        return ;
    }
    --size[now];
    if(data[now]<x)
        del(ch[now][1],x);
    else
        del(ch[now][0],x);
    return ;
}

int get_rank(int x){
    int now=root,basic=0;
    while(1){
        if(!now)break;
        if(data[now]==x){basic+=size[ch[now][0]]+1;break;}
        if(x<data[now])now=ch[now][0];
        else    basic+=size[ch[now][0]]+tot[now],now=ch[now][1];
    }
    return basic;
}

int get_num(int x){
    int now=root;
    while(1){
        if(!now)return 0;
        if(x<=size[ch[now][0]]){
            now=ch[now][0];
            continue;
        }
        if(x>size[ch[now][0]]+tot[now]){
            x-=size[ch[now][0]]+tot[now];
            now=ch[now][1];
            continue;
        }
        else
            return data[now];
    }
}

void front(int x){
    int now=root;
    while(1){
        if(!now)return ;
        if(data[now]<x)
            ans=now,now=ch[now][1];
        else
            now=ch[now][0];
    }
    return ;
}

void back(int x){
    int now=root;
    while(1){
        if(!now)return ;
        if(x<data[now])
            ans=now,now=ch[now][0];
        else
            now=ch[now][1];
    }
    return ;
}

int main(){
    freopen("in","r",stdin);
//  srand(time(0));
    read(n);
    int opt,x;
    while(n--){
        read(opt);read(x);
        switch(opt){
            case 1:ins(root,x);break;
            case 2:del(root,x);break;
            case 3:printf("%d\n",get_rank(x));break;
            case 4:printf("%d\n",get_num(x));break;
            case 5:ans=0;front(x);printf("%d\n",data[ans]);break;
            case 6:ans=0;back(x);printf("%d\n",data[ans]);break;
            default :puts("ERROR IN INPUT");return 0;
        }
    }
    return 0;
}

SBT 版:

#include<bits/stdc++.h>
using namespace std;
#define cl(x) memset(x,0,sizeof(x))
#define rg register

template <typename _Tp> inline void read(_Tp&x){
    char c11=getchar();x=0;bool booo=0;
    while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-'){c11=getchar();booo=1;}
    while(isdigit(c11)){x=x*10+c11-'0';c11=getchar();}if(booo)x=-x;return ;
}

const int N=1005000;

struct sbt{
    int rt,sz;
    int data[N],ch[N][2],size[N];
    void clear(){
        rt=sz=0;
        cl(data),cl(ch),cl(size);
    }
    void zig(int &p){
        int k=ch[p][1];
        ch[p][1]=ch[k][0];
        ch[k][0]=p;
        size[k]=size[p];
        size[p]=size[ch[p][0]]+size[ch[p][1]]+1;
        p=k;
    }
    void zag(int &p){
        int k=ch[p][0];
        ch[p][0]=ch[k][1];
        ch[k][1]=p;
        size[k]=size[p];
        size[p]=size[ch[p][0]]+size[ch[p][1]]+1;
        p=k;
    }
    void maintain(int &p,bool flag){
        #define L ch[p][0]
        #define R ch[p][1]
        #define LL ch[ch[p][0]][0]
        #define LR ch[ch[p][0]][1]
        #define RL ch[ch[p][1]][0]
        #define RR ch[ch[p][1]][1]
        if(!flag)
            if(size[LL]>size[R])zag(p);
            else
                if(size[LR]>size[R]){zig(L);zag(p);}
                else return ;
        else
            if(size[RR]>size[L])zig(p);
            else
                if(size[RL]>size[L]){zag(R);zig(p);}
                else return ;
        maintain(L,0);
        maintain(R,1);
        maintain(p,1);
        maintain(p,0);
        return ;
    }
    void ins(int &p,int x){
        if(!p){
            p=++sz;data[sz]=x,size[sz]=1;
            return ;
        }
        ++size[p];
        ins(ch[p][data[p]<=x],x);
        maintain(p,x>=data[p]);
    }
    int erase(int &p,int x){
        --size[p];int tmp;
        if(x==data[p]||(x<data[p]&&!ch[p][0])||(data[p]<x&&!ch[p][1])){
            tmp=data[p];
            if(!ch[p][0]||!ch[p][1])p=ch[p][0]+ch[p][1];
            else data[p]=erase(ch[p][0],data[p]+1);
            return tmp;
        }
        tmp=erase(ch[p][data[p]<=x],x);
        return tmp;
    }
    int rank(int &p,int x){
        if(!p)return 1;int tmp=0;
        if(x<=data[p])tmp=rank(ch[p][0],x);
        else tmp=size[ch[p][0]]+1+rank(ch[p][1],x);
        return tmp;
    }
    int num(int &p,int x){
        if(x==size[ch[p][0]]+1)return data[p];
        if(x<=size[ch[p][0]])return num(ch[p][0],x);
        return num(ch[p][1],x-1-size[ch[p][0]]);
    }
    int front(int &p,int x){
        if(!p)return x;int tmp;
        if(x<=data[p])tmp=front(ch[p][0],x);
        else{tmp=front(ch[p][1],x);if(tmp==x)tmp=data[p];}
        return tmp;
    }
    int back(int &p,int x){
        if(!p)return x;int tmp;
        if(data[p]<=x)tmp=back(ch[p][1],x);
        else{tmp=back(ch[p][0],x);if(tmp==x)tmp=data[p];}
        return tmp;
    }
}T;

int main(){
    freopen("in","r",stdin);
    int m;read(m);
    T.clear();
    int &rt=T.rt=0;
    while(m--){
        int opt,x;
        read(opt);read(x);
        switch(opt){
            case 1:T.ins(rt,x);break;
            case 2:T.erase(rt,x);break;
            case 3:printf("%d\n",T.rank(rt,x));break;
            case 4:printf("%d\n",T.num(rt,x));break;
            case 5:printf("%d\n",T.front(rt,x));break;
            case 6:printf("%d\n",T.back(rt,x));break;
        }
    }
    return 0;
}

相關推薦

模板bzoj-3224普通平衡(splay&treap&SBT)

先吐槽一下,要找塊好模板真不容易,畢竟大家都有各自的程式碼風格,強迫自己去看非自己風格的程式碼真是痛苦,所以在網上新增一種型別的模板 最近才發現這題A了三遍,分別是以三種平衡樹的模板題A的,所以稍微彙總一下,讓後來者有個型別的模板可以依靠 相信看模板的人都看

紅黑 ------ luogu P3369 模板普通平衡Treap/SBT

div child lin main false tchar clas char als 二次聯通門 : luogu P3369 【模板】普通平衡樹(Treap/SBT) 近幾天閑來無事。。。就把各種平衡樹都寫了一下。。。 下面是紅黑樹(Red Black Tree)

替罪羊 ------ luogu P3369 模板普通平衡Treap/SBT

nod %d clas https number problem 普通 true ble 二次聯通門 : luogu P3369 【模板】普通平衡樹(Treap/SBT) 閑的沒事,把各種平衡樹都寫寫 比較比較。。。 下面是替罪羊樹 #include &l

數組splay ------ luogu P3369 模板普通平衡Treap/SBT

普通 模板 char truct div color fine col suffix 二次聯通門 : luogu P3369 【模板】普通平衡樹(Treap/SBT) #include <cstdio> #define Max 100005

fhq treap ------ luogu P3369 模板普通平衡Treap/SBT

ret true read std stdin urn tdi ref code 二次聯通門 : LibreOJ #104. 普通平衡樹 #include <cstdio> #include <iostream> #include

luogu3369 模板普通平衡Treap/SBT

oid sin markdown 隨機 節點 nod -m rotate 編號 treap做法,參考hzwer的博客 #include <iostream> #include <cstdlib> #include <cstdio> usi

題解 P3369 模板普通平衡Treap/SBT

為什麽 平衡樹 -m cout 指向 erase out 刪除 play STL真是個好東西。 最近在看pb_ds庫及vector和set的用法,就想用這三種操作來實現一下普通平衡樹,結果pb_ds中的rbtree不支持重復值,而本蒟蒻也看不懂不懂各大佬用pb_ds的實現,

模板普通平衡Treap/SBT

gpo splay 格式 可能 bit bsp inf ron 表示 題目描述 您需要寫一種數據結構(可參考題目標題),來維護一些數,其中需要提供以下操作: 插入x數 刪除x數(若有多個相同的數,因只刪除一個) 查詢x數的排名(排名定義為比當前數小的數的個數+1

luogu P3369 模板普通平衡Treap/SBT

AS += amp father https ota fin size insert 題目鏈接:https://www.luogu.org/problemnew/show/P3369 #include <cstdio> #include <algorith

洛谷 P3369 模板普通平衡Treap/SBT

題目描述 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作: 1.插入x數 2.刪除x數(若有多個相同的數,因只刪除一個) 3.查詢x數的排名(若有多個相同的數,因輸出最小的排名) 4.查詢排名為x的數 5.求x的前驅(前驅

[BZOJ 3224] 普通平衡 非旋Treap

查詢 getchar printf ++ return type clas else rank 題意   維護一個多重集合 $S$ , 支持:     ① 插入一個數 $w$ .     ② 刪除一個數 $w$ .     ③ 查詢 $w$ 在集合中的排名.     ④ 查

Bzoj 3224.普通平衡 [ 權值線段 ]

Description 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作: 1. 插入x數 2. 刪除x數(若有多個相同的數,因只刪除一個) 3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名) 4. 查詢排名為x的數 5. 求x的前驅(前驅

luoguP5055 模板可持久化文藝平衡

https://www.luogu.org/problemnew/show/P5055 如果你還不會可持久化平衡樹,請右轉洛谷題解區 我們考慮一下可持久化的複雜度為什麼是正確的 每一次操作時,$ fhq $ $ treap $ 的複雜度是期望 $ log ( n ) $ 的,而 $ Splay $ 是均

Luogu 3369 / BZOJ 3224 - 普通平衡 - [替罪羊]

題目連結: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 https://www.luogu.org/problemnew/show/P3369 Description 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下

Luogu 3369 / BZOJ 3224 - 普通平衡 - [無旋Treap]

題目連結: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 https://www.luogu.org/problemnew/show/P3369 Description 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下

[Luogu P5055] 模板可持久化文藝平衡

洛谷傳送門 題目描述 您需要寫一種資料結構,來維護一個序列,其中需要提供以下操作(對於各個以往的歷史版本): 在第 p

Luogu5055 模板可持久化文藝平衡(fhq-treap

  注意下傳標記時也需要新建節點。空間開的儘量大。 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #inclu

洛谷p5055模板可持久化文藝平衡

關於 clone tex mat clas long long pri rand() out 可持久化\(\text{fhq-treap}\)。 比較常用的平衡樹一般就是\(\text{fhq-treap}\)和\(\text{splay}\)了,因為\(\text{spl

treapbzoj 3224: Tyvj 1728 普通平衡

加上了前驅和後繼 //#define _TEST _TEST #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #inc

bzoj 3224Tyvj 1728 普通平衡

Tyvj 1728 普通平衡樹 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 11767 Solved: 5021 [Submit][Status][Discuss] Description 您需要