\(fhq-treap\)实现。
正文部分
\(fhq-treap\)的所有操作都在两个\(split\)的基础上,一次\(val\),一次\(size\)
注意:这里我们是将小于等于操作数的值分为一棵树,其余分为另一棵树
分离和合并的过程很简单,学的话可以看我的代码手动模拟一下,这个过程应该不是很难。
对于一个数\(x\)的插入,我们先已这个值分一次\(val\),然后创建新节点和并即可。
对于一个数\(x\)的删除,我们先已\(x\)分一次\(val\),然后在分出来的左子树里已\(x-1\)分一次\(val\),最后产生的右子树我们将其左右孩子合并即可。
对于一个数\(x\)的排名,我们将其以\(x-1\)分一次\(val\),然后输出左子树的\(size+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;
}