BZOJ 3224 Tyvj 1728 普通平衡树
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598Sample Output
106465
84185
492737HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
终于打完了splay, 不过还是全程抄代码。
%%%DQS,您是我们的红太阳!没有您我们会死!
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long LL;
const int SZ = 1000010;
const int INF = 1000000010;
struct node
{
node *ch[2], *f;
int sz, cnt, v;
void maintain()
{
sz = cnt + ch[0] -> sz + ch[1] -> sz;
}
int cmp(int x)
{
if(x == v) return -1;
return x < v ? 0 : 1;
}
int dir()
{
return f -> ch[1] == this;
}
void setc(node *x, int d)
{
(ch[d] = x) -> f = this;
}
}T[SZ], *root, *null;
int Tcnt = 0;
node* newnode(int x, node *f)
{
node *k = T + (++ Tcnt);
k -> v = x;
k -> ch[0] = k -> ch[1] = null;
k -> sz = k -> cnt = 1;
k -> f = f;
return k;
}
void rotate(node *p)
{
node *fa = p -> f;
int d = p -> dir();
fa -> f -> setc(p, fa -> dir());
fa -> setc(p -> ch[d ^ 1], d); fa -> maintain();
p -> setc(fa, d ^ 1); p -> maintain();
if(fa == root) root = p;
}
void splay(node *p, node *rt = null)
{
while(p -> f != rt)
{
if(p -> f -> f == rt)
rotate(p);
else
{
if(p -> dir() == p -> f -> dir())
rotate(p -> f), rotate(p);
else
rotate(p), rotate(p);
}
}
p -> maintain();
}
void insert(node *p, int x)
{
if(root == null)
{
root = newnode(x, null);
return ;
}
while(p != null)
{
p -> sz ++;
int d = p -> cmp(x);
if(d == -1)
{
p -> cnt ++;
break;
}
if(p -> ch[d] == null)
{
p -> ch[d] = newnode(x, p);
p = p -> ch[d];
break;
}
p = p -> ch[d];
}
splay(p);
}
void erase(node *p, int x)
{
while(p != null)
{
p -> sz --;
int d = p -> cmp(x);
if(d == -1)
{
p -> cnt --;
break;
}
p = p -> ch[d];
}
if(p -> cnt)
return ;
splay(p);
if(p -> ch[0] == null)
{
root = p -> ch[1];
root -> f = null;
return ;
}
if(p -> ch[1] == null)
{
root = p -> ch[0];
root -> f = null;
return ;
}
p = p -> ch[0];
while(p -> ch[1] != null) p = p -> ch[1];
splay(p, root);
p -> ch[1] = root -> ch[1]; p -> ch[1] -> f = p;
p -> f = null; p -> maintain();
root = p;
}
int ask_rank(node *p, int x)
{
int ans = 0;
while(p != null)
{
int d = p -> cmp(x);
if(d == -1) return ans + p -> ch[0] -> sz + 1;
if(d == 1) ans += p -> ch[0] -> sz + p -> cnt;
p = p -> ch[d];
}
return -1;
}
int ask_num(node *p, int k)
{
while(p != null)
{
int l = p -> ch[0] -> sz + 1;
int r = p -> ch[0] -> sz + p -> cnt;
if(l <= k && k <= r) return p -> v;
if(k > r) k -= r, p = p -> ch[1];
else p = p -> ch[0];
}
}
int ask_pre(node *p, int x)
{
int ans = 0;
while(p != null)
{
if(p -> v < x)
ans = p -> v, p = p -> ch[1];
else
p = p -> ch[0];
}
return ans;
}
int ask_suf(node *p, int x)
{
int ans = 0;
while(p != null)
{
if(p -> v > x)
ans = p -> v, p = p -> ch[0];
else
p = p -> ch[1];
}
return ans;
}
void init()
{
null = newnode(-INF, null);
null -> sz = null -> cnt = 0;
root = null;
}
int main()
{
init();
int n;
scanf("%d", &n);
while(n--)
{
int op, x;
scanf("%d%d", &op, &x);
switch(op)
{
case 1 : insert(root, x); break;
case 2 : erase(root, x); break;
case 3 : printf("%d\n", ask_rank(root, x)); break;
case 4 : printf("%d\n", ask_num(root, x)); break;
case 5 : printf("%d\n", ask_pre(root, x)); break;
case 6 : printf("%d\n", ask_suf(root, x)); break;
}
}
return 0;
}