链接
题目描述
思路
Treap模板
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int size[100005], s[100005][2];
int v[100005], pos[100005];
int n, root, opt, x, cnt, num;
void up(int x)
{
size[x] = size[s[x][0]] + size[s[x][1]] + 1;
}
void trrn(int &num, int p)
{
int t=s[num][p];
s[num][p]=s[t][!p],s[t][!p]=num,up(num),up(t),num=t;
}
void insert(int x, int &num)
{
if(!num)
{
num = ++cnt;
size[num] = 1;
v[num] = x;
pos[num] = rand();
return;
}//当前点是空点
size[num]++;
if(x <= v[num]) {
insert(x, s[num][0]);
if(pos[s[num][0]] < pos[num]) trrn(num, 0);
}
else {
insert(x, s[num][1]);
if(pos[s[num][1]] < pos[num]) trrn(num, 1);
}
return;
}
void del(int x, int &num)
{
if(v[num] == x) {
if(s[num][0] * s[num][1] == 0) {num = s[num][0] + s[num][1]; return;}//直接让它父亲连向它唯一的儿子
else if(pos[s[num][0]] > pos[s[num][1]]) {
trrn(num, 1);
del(x, s[num][0]);
}
else {
trrn(num, 0);
del(x, s[num][1]);
}
}
else if(v[num] > x) del(x, s[num][0]);
else del(x, s[num][1]);
up(num);
}
int ask_rank(int x, int num)
{
if(!num) return 1;
if(v[num] >= x) return ask_rank(x, s[num][0]);
return ask_rank(x, s[num][1]) + size[s[num][0]] + 1;
}
int find_rank(int x, int num)
{
if(size[s[num][0]] == x - 1) return v[num];
if(size[s[num][0]] >= x) return find_rank(x, s[num][0]);
return find_rank(x - size[s[num][0]] - 1, s[num][1]);
}
int find_pre(int x, int num)
{
if(!num) return -20000005;
if(v[num] < x) return max(v[num], find_pre(x, s[num][1]));
else return find_pre(x, s[num][0]);
}
int find_nxt(int x, int num)
{
if(!num) return 20000005;
if(v[num] > x) return min(v[num], find_nxt(x, s[num][0]));
else return find_nxt(x, s[num][1]);
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
{
scanf("%d%d", &opt, &x);
if(opt == 1) insert(x, num);
if(opt == 2) del(x, num);
if(opt == 3) printf("%d\n", ask_rank(x, num));
if(opt == 4) printf("%d\n", find_rank(x, num));
if(opt == 5) printf("%d\n", find_pre(x, num));
if(opt == 6) printf("%d\n", find_nxt(x, num));
}
return 0;
}