fhq treap抄襲筆記
阿新 • • 發佈:2018-11-29
目錄
fhq treap
碎碎念
我咋感覺合併這麼像左偏樹呢
ps:難道你們的treap都是小頭堆的嗎
fhq真的是神人
現在看以前學的splay是有點噁心,尤其是壓行壓不過fhqtreap
點一下
fhq treap主要操作就倆
拆(merge)和合(split)
其他操作都是基於這倆操作(拆拆合合,合拆合拆,拆了又和,合了又拆)
合併操作merge
把兩顆樹合併成一顆
這裡的兩顆樹x,y,滿足x樹小於y樹
因為要保證堆的性質
if(!x||!y) return x+y;//必有一顆為空,所以直接返回那顆不空樹即可 if(pri[x]<pri[y]) {//這裡x為根,因為x樹<y樹,所以y一定在x的右孩子中 ch[x][1]=merge(ch[x][1],y); pushup(x);//更新size return x; } else {//類似的,自己想 ch[y][0]=merge(x,ch[y][0]);//這裡的merge順序千萬不要顛倒,因為要x樹<y樹 pushup(y); return y; } }
拆分操作split
不太會說,不說了,自己去領悟吧
其他操作看這裡
模板
#include <bits/stdc++.h> #define FOR(i,a,b) for(int i=a;i<=b;++i) using namespace std; const int maxn=1e5+7; inline int read() { int x=0,f=1;char s=getchar(); for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1; for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0'; return x*f; } int ch[maxn][2],val[maxn],pri[maxn],size[maxn],siz,cnt; int make_edge(int x) { val[++cnt]=x,pri[cnt]=rand(),size[cnt]=1; return cnt; } void pushup(int x) { size[x]=size[ch[x][0]]+size[ch[x][1]]+1; } int merge(int x,int y) { if(!x||!y) return x+y; if(pri[x]<pri[y]) { ch[x][1]=merge(ch[x][1],y); pushup(x); return x; } else { ch[y][0]=merge(x,ch[y][0]); pushup(y); return y; } } void split(int now,int k,int &x,int &y) { if(!now) x=y=0; else { if(val[now]<=k) x=now,split(ch[now][1],k,ch[x][1],y); else y=now,split(ch[now][0],k,x,ch[y][0]); pushup(now); } } int k_th(int now,int k) { while(233) { if(k==size[ch[now][0]]+1) return now; if(k<=size[ch[now][0]]) now=ch[now][0]; else k-=size[ch[now][0]]+1,now=ch[now][1]; } } int main() { srand(time(NULL)); int n=read(),x,y,z,rt=0; FOR(i,1,n) { int opt=read(),a=read(); if(opt==1) { split(rt,a,x,y); rt=merge(merge(x,make_edge(a)),y); } else if(opt==2) { split(rt,a,x,z); split(x,a-1,x,y); y=merge(ch[y][0],ch[y][1]); rt=merge(merge(x,y),z); } else if(opt==3) { split(rt,a-1,x,y); cout<<size[x]+1<<"\n"; rt=merge(x,y); } else if(opt==4) { cout<<val[k_th(rt,a)]<<"\n"; } else if(opt==5) { split(rt,a-1,x,y); cout<<val[k_th(x,size[x])]<<"\n"; rt=merge(x,y); } else if(opt==6) { split(rt,a,x,y); cout<<val[k_th(y,1)]<<"\n"; rt=merge(x,y); } } return 0; }