fhq treap 范浩强平衡树
https://www.luogu.com.cn/problem/P3369
随机大法好啊啊啊
插入数字的时候,把平衡树按x分裂,插入x后再合并,具体可以看代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<ctime>
#include<stack>
using namespace std;
const int maxn = 2e6+10;
struct Node{
int l,r;
int val,key;
int siz;
}tree[maxn];
int l,r,cnt,p,x,n;
void update(int node){
tree[node].siz = tree[tree[node].l].siz + tree[tree[node].r].siz + 1;
}
void split(int node,int x,int& l,int& r){//node分裂成l和r,l--val<= x r--val > x
if(node == 0){
l = r = 0;
return ;
}
if(tree[node].val <= x){//左边部分
l = node;
//左边儿子改了,继续分右边
split(tree[node].r,x,tree[node].r,r);
}
else{
r = node;
split(tree[node].l,x,l,tree[node].l);
}
update(node);
}
int add(int val){
cnt++;
tree[cnt].siz = 1;
tree[cnt].l = tree[cnt].r = 0;
tree[cnt].val = val;
tree[cnt].key = rand();
}
int merge(int l,int r){
if(!l || !r) return l + r;//总有一个是叶子
if(tree[l].key <= tree[r].key){//l做父亲 ,r比l大,所以r接上l的右子树
tree[l].r = merge(tree[l].r,r);
update(l);
return l;
}
else{
tree[r].l = merge(l,tree[r].l);
update(r);
return r;
}
}
int kth(int node,int k){//排名第k的数字
if(k <= tree[tree[node].l].siz){
return kth(tree[node].l,k);
}
else if(tree[tree[node].l].siz + 1 == k){
return node;
}
else{
k -= tree[tree[node].l].siz + 1;
return kth(tree[node].r,k);
}
}
//int kth(int u,int k)
//{//求排名第k的数
// if(k<=tree[tree[u].l].siz)//在左区间
// return kth(tree[u].l,k);
// else if(k==tree[tree[u].l].siz+1)//这个数为此区间的根
// return u;
// else
// {
// k-=(tree[tree[u].l].siz+1);//排名为k要减少左儿子的节点数
// return kth(tree[u].r,k);//在右区间
// }
//}
int main(){
int n;
scanf("%d",&n);
int root = 0;
int p;
srand((unsigned)time(NULL));
while(n--){
int op,x;
scanf("%d %d",&op,&x);
if(op == 1){
split(root,x,l,r);// node分裂成l和r,l--val<= x r--val > x
add(x);
root = merge(merge(l,cnt),r);
}
else if(op == 2){//删除x
split(root,x,l,r);
split(l,x-1,l,p);
p = merge(tree[p].l,tree[p].r);//可能有多个x
root = merge(merge(l,p),r);
}
else if(op == 3){//查询x的排名
split(root,x-1,l,r);
printf("%d\n",tree[l].siz+1);//小于x的个数
root = merge(l,r);
}
else if(op == 4){//排名为x的数,记录重复
printf("%d\n",tree[kth(root,x)].val);
}
else if(op == 5){
split(root,x-1,l,r);
printf("%d\n",tree[kth(l,tree[l].siz)].val);
root = merge(l,r);
}
else{
split(root,x,l,r);
printf("%d\n",tree[kth(r,1)].val);
root = merge(l,r);
}
}
return 0;
}
寻找真正的热爱

浙公网安备 33010602011771号