[模板]fhqTreap

用途

平衡树(可实现区间翻转)

原理

和treap一样,中序遍历表示权值的顺序,并且每个点有一个随机的附加值,形成一个堆来保证复杂度

但是不旋转,所有操作通过split和merge实现

分为两种split:按权值和按排名

代码

luogu3369 普通平衡树

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define CLR(a,x) memset(a,x,sizeof(a))
  4 #define MP make_pair
  5 #define fi first
  6 #define se second
  7 using namespace std;
  8 typedef long long ll;
  9 typedef unsigned long long ull;
 10 typedef unsigned int ui;
 11 typedef long double ld;
 12 const int maxn=1e5+10;
 13 
 14 inline char gc(){
 15     return getchar();
 16     static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf;
 17     return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
 18 }
 19 inline ll rd(){
 20     ll x=0;char c=gc();bool neg=0;
 21     while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();}
 22     while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc();
 23     return neg?(~x+1):x;
 24 }
 25 
 26 int N,val[maxn],rdt[maxn],siz[maxn],ch[maxn][2],pct,root;
 27 
 28 inline int newnode(int x){
 29     int p=++pct;
 30     val[p]=x;
 31     rdt[p]=rand()<<15|rand();
 32     siz[p]=1;
 33     ch[p][0]=ch[p][1]=0;
 34     return p;
 35 }
 36 
 37 inline void print(int x){
 38     if(!x) return;
 39     print(ch[x][0]);
 40     printf("##%d %d %d %d %d %d\n",x,val[x],rdt[x],siz[x],ch[x][0],ch[x][1]);
 41     print(ch[x][1]);
 42 }
 43 
 44 inline void update(int x){siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]];}
 45 
 46 inline void splitbyrnk(int x,int &l,int &r,int k){
 47     if(!k) l=0,r=x;
 48     else if(k==siz[x]) l=x,r=0;
 49     else if(k<=siz[ch[x][0]]) r=x,splitbyrnk(ch[x][0],l,ch[x][0],k),update(x);
 50     else l=x,splitbyrnk(ch[x][1],ch[x][1],r,k-siz[ch[x][0]]-1),update(x);
 51 }
 52 
 53 inline void splitbyval(int x,int &l,int &r,int k){ //等于的归右面
 54     if(!x) l=r=0;
 55     else if(k<=val[x]) r=x,splitbyval(ch[x][0],l,ch[x][0],k),update(x);
 56     else l=x,splitbyval(ch[x][1],ch[x][1],r,k),update(x);
 57 }
 58 
 59 inline void merge(int &x,int l,int r){
 60     if(!l||!r) x=l+r;
 61     else if(rdt[l]<rdt[r]) x=l,merge(ch[x][1],ch[x][1],r),update(x);
 62     else x=r,merge(ch[x][0],l,ch[x][0]),update(x);
 63 }
 64 
 65 inline void insert(int x){
 66     int p=newnode(x);
 67     int l,r;splitbyval(root,l,r,x);
 68     merge(r,p,r);
 69     merge(root,l,r);
 70 }
 71 
 72 inline void del(int x){
 73     int l,r;splitbyval(root,l,r,x);
 74     int p;splitbyrnk(r,p,r,1);
 75     merge(root,l,r);
 76 }
 77 
 78 inline int getrnk(int x){
 79     int l,r;splitbyval(root,l,r,x);
 80     int re=siz[l];
 81     merge(root,l,r);
 82     return re+1;
 83 }
 84 
 85 inline int getval(int x){
 86     int l,r;splitbyrnk(root,l,r,x-1);
 87     int p;splitbyrnk(r,p,r,1);
 88     int re=val[p];
 89     merge(r,p,r);merge(root,l,r);
 90     return re;
 91 }
 92 
 93 inline int getpre(int x){
 94     return getval(getrnk(x)-1);
 95 }
 96 
 97 inline int getnxt(int x){
 98     return getval(getrnk(x+1));
 99 }
100 
101 int main(){
102     //freopen("","r",stdin);
103     root=newnode(1e9);
104     N=rd();
105     for(int i=1;i<=N;i++){
106         int op=rd(),x=rd();
107         if(op==1) insert(x);
108         else if(op==2) del(x);
109         else if(op==3) printf("%d\n",getrnk(x));
110         else if(op==4) printf("%d\n",getval(x));
111         else if(op==5) printf("%d\n",getpre(x));
112         else printf("%d\n",getnxt(x));
113     }
114     return 0;
115 }

 

上一篇:2021-1-31 AcWing 寒假每日一题 898 数字三角形


下一篇:[NOI2014]随机数生成器 题解