洛谷P3369【模板】普通平衡樹
阿新 • • 發佈:2019-02-11
names 實現 oid for printf namespace treenode ret 找到 分一次\(val\),然後輸出左子樹的\(size+1\)即可
對於找到排名為\(x\)的數,我們直接求一次\(kth\)就好了
對於求\(x\)的前驅,我們將其已\(x-1\)分一次\(val\),然後在左子樹裏找到\(kth\)為左子樹的\(size\)的節點就好了
對於求\(x\)的後續,我們已\(x\)分一次\(val\),然後在右子樹裏找到\(kth\)為\(1\)的節點即可
\(fhq-treap\)實現。
正文部分
\(fhq-treap\)的所有操作都在兩個\(split\)的基礎上,一次\(val\),一次\(size\)
註意:這裏我們是將小於等於操作數的值分為一棵樹,其余分為另一棵樹
分離和合並的過程很簡單,學的話可以看我的代碼手動模擬一下,這個過程應該不是很難。
對於一個數\(x\)的插入,我們先已這個值分一次\(val\),然後創建新節點和並即可。
對於一個數\(x\)的刪除,我們先已\(x\)分一次\(val\),然後在分出來的左子樹裏已\(x-1\)分一次\(val\),最後產生的右子樹我們將其左右孩子合並即可。
對於一個數\(x\)的排名,我們將其以\(x-1\)
對於找到排名為\(x\)的數,我們直接求一次\(kth\)就好了
對於求\(x\)的前驅,我們將其已\(x-1\)分一次\(val\),然後在左子樹裏找到\(kth\)為左子樹的\(size\)的節點就好了
對於求\(x\)的後續,我們已\(x\)分一次\(val\),然後在右子樹裏找到\(kth\)為\(1\)的節點即可
My Code:
#include <bits/stdc++.h> #define il inline #define temp template<class T> const int MAXN = 1e5 + 10; using namespace std; temp il void rd(T& res) { res = 0;char c;bool sign = 0; for(c = getchar();!isdigit(c);c = getchar()) sign |= c == ‘-‘; for(;isdigit(c);c = getchar()) res = (res << 1) + (res << 3) + (c ^ 48); (sign) && (res = -res); return; } struct TreeNode { int ch[2],size,val,rnd; }tr[MAXN]; int n,m,i,j,k,q,cnt,root,y,z; il int NewNode(int v) { tr[++cnt].size = 1; tr[cnt].val = v;tr[cnt].rnd = rand(); return cnt; } il void pushup(int o) { tr[o].size = tr[tr[o].ch[0]].size + tr[tr[o].ch[1]].size + 1; return; } int merge(int u,int v) { if(!u) return v;if(!v) return u; if(tr[u].rnd < tr[v].rnd) { tr[u].ch[1] = merge(tr[u].ch[1],v); pushup(u); return u; } else { tr[v].ch[0] = merge(u,tr[v].ch[0]); pushup(v); return v; } } void split_v(int now,int k,int& x,int& y) { if(!now) x = y = 0; else { if(tr[now].val <= k) x = now,split_v(tr[now].ch[1],k,tr[now].ch[1],y); else y = now,split_v(tr[now].ch[0],k,x,tr[now].ch[0]); pushup(now); } return; } il int kth(int u,int k) { while(1) { if(k <= tr[tr[u].ch[0]].size) { u = tr[u].ch[0]; } else { if(k == tr[tr[u].ch[0]].size + 1) return u; k -= tr[tr[u].ch[0]].size + 1;u = tr[u].ch[1]; } } } int main() { srand((unsigned)time(NULL)); rd(q); while(q--) { int opt,x;rd(opt);rd(x); if(opt == 1) { split_v(root,x,y,z); root = merge(merge(y,NewNode(x)),z); } else if(opt == 2) { int k; split_v(root,x,y,k); split_v(y,x - 1,y,z); z = merge(tr[z].ch[0],tr[z].ch[1]); root = merge(y,merge(z,k)); } else if(opt == 3) { split_v(root,x - 1,y,z); printf("%d\n",tr[y].size + 1); root = merge(y,z); } else if(opt == 4) { printf("%d\n",tr[kth(root,x)].val); } else if(opt == 5) { split_v(root,x - 1,y,z); printf("%d\n",tr[kth(y,tr[y].size)].val); root = merge(y,z); } else { split_v(root,x,y,z); printf("%d\n",tr[kth(z,1)].val); root = merge(y,z); } } return 0; }
洛谷P3369【模板】普通平衡樹