P3369 【模板】普通平衡树
【模板】普通平衡树
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 1. 插入 $x$ 数 2. 删除 $x$ 数(若有多个相同的数,因只删除一个) 3. 查询 $x$ 数的排名(排名定义为比当前数小的数的个数 $+1$ ) 4. 查询排名为 $x$ 的数 5. 求 $x$ 的前驱(前驱定义为小于 $x$,且最大的数) 6. 求 $x$ 的后继(后继定义为大于 $x$,且最小的数)
输入输出格式
输入格式
第一行为 $n$,表示操作的个数,下面 $n$ 行每行有两个数 $\text{opt}$ 和 $x$,$\text{opt}$ 表示操作的序号( $ 1 \leq \text{opt} \leq 6 $ )
输出格式
对于操作 $3,4,5,6$ 每行输出一个数,表示对应答案
输入输出样例
输入样例 #1
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例 #1
106465
84185
492737
说明
【数据范围】 对于 $100\%$ 的数据,$1\le n \le 10^5$,$|x| \le 10^7$
FHQ(分裂式Treap)实现
#include <bits/stdc++.h>
using namespace std;
#define getsize(x) (x ? x -> size : 0)
#define ll long long
const int MAXN = 1e5 + 10;
class FHQ
{
public :
class Node
{
public :
int key, rank;
int size;
Node *ls, *rs;
void push_up()
{
size = getsize(ls) + getsize(rs) + 1;
}
}pool[2 * MAXN], *rt;
int top;
//分裂 p 返回 p 的左子p_l, 右子p_r
void split(Node *p , Node *&p_l, Node *&p_r, int x)//分裂当前子树
{
if(!p)//p 为空,无需分离
{
p_l = p_r = NULL;
return ;
}
if(p -> key <= x)//如果 p 的值比 x 小,就把 p 接到左子上,继续分裂 p 的右子
{
p_l = p;
split(p -> rs, p_l -> rs, p_r, x);
p_l -> push_up();
}
else//否则分 p 的左子
{
p_r = p;
split(p -> ls, p_l ,p_r -> ls, x);
p_r -> push_up();
}
}
void merge(Node *&p, Node *p_l, Node *p_r)
{
if(!p_l || !p_r)//如果有一为空
{
p = p_l ? p_l : p_r;
return ;
}
if(p_l -> rank < p_r -> rank)//维护平衡
{
p = p_l;
merge(p -> rs, p_l -> rs, p_r);
}
else
{
p = p_r;
merge(p -> ls, p_l, p_r -> ls);
}
p -> push_up();
}
Node *newNode(int x)
{
Node *p = pool + (++top);
p -> key = x;
p -> rank = rand();
p -> size = 1;
return p;
}
void insert(Node *&rt, int x)
{
Node *p1, *p2;
split(rt, p1, p2 ,x - 1);
merge(rt, p1 ,newNode(x));
merge(rt, rt, p2);
}
void remove(Node *&rt, int x)
{
Node *p1, *p2, *p3 , *p4;
split(rt, p1 ,p2 ,x - 1);
split(p2, p3 ,p4, x);
merge(p3, p3 -> ls, p3 -> rs);
merge(p3, p3, p4);
merge(rt, p1, p3);
}
int getRank(Node *&rt, int x)
{
Node *p1 ,*p2;
split(rt, p1 ,p2, x - 1);
int ans = getsize(p1);
merge(rt, p1 ,p2);
return ans;
}
int getKey(Node *p, int rank)
{
while(p)
{
if(rank <= getsize(p -> ls))
p = p -> ls;
else if(rank > getsize(p -> ls) + 1)
{
rank -= getsize(p -> ls) + 1;
p = p -> rs;
}
else return p -> key;
}
return 0;
}
int lower(Node *p, int x)
{
int ans = INT_MIN;
while(p)
{
if(x > p -> key)
{
ans = max(ans, p -> key);
p = p -> rs;
}
else p = p -> ls;
}
return ans;
}
int upper(Node *p, int x)
{
int ans = INT_MAX;
while(p)
{
if(x < p -> key)
{
ans = min(ans, p -> key);
p = p -> ls;
}
else p = p -> rs;
}
return ans;
}
}FHQ;
int t;
int op, x;
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d %d", &op, &x);
if(op == 1)
{
FHQ.insert(FHQ.rt, x);
}
if(op == 2)
{
FHQ.remove(FHQ.rt, x);
}
if(op == 3)
{
printf("%d\n", FHQ.getRank(FHQ.rt, x) + 1);
}
if(op == 4)
{
printf("%d\n", FHQ.getKey(FHQ.rt, x));
}
if(op == 5)
{
printf("%d\n" , FHQ.lower(FHQ.rt, x));
}
if(op == 6)
{
printf("%d\n", FHQ.upper(FHQ.rt, x));
}
}
return 0;
}

浙公网安备 33010602011771号