# bzoj3224 Tyvj 1728 普通平衡树

## 3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 18119  Solved: 7981
[Submit][Status][Discuss]

## Description

1. 插入x数
2. 删除x数(若有多个相同的数，因只删除一个)
3. 查询x数的排名(若有多个相同的数，因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x，且最大的数)
6. 求x的后继(后继定义为大于x，且最小的数)

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

106465
84185
492737

## HINT

1.n的数据范围：n<=100000

2.每个数的数据范围：[-2e9,2e9]

## Source

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 200010;
int n,m,sizee[maxn],pos[maxn],tot,root,a[maxn];

struct node
{
int fa,left,right,v,cnt;
}e[maxn];

void update(int x)
{
sizee[x] = e[x].cnt;
if (e[x].left != -1)
sizee[x] += sizee[e[x].left];
if (e[x].right != -1)
sizee[x] += sizee[e[x].right];
}

int getsize(int x)
{
if (x == -1)
return 0;
return sizee[x];
}

void turnr(int x)
{
int y = e[x].fa;
int z = e[y].fa;
e[y].left = e[x].right;
if (e[x].right != -1)
e[e[x].right].fa = y;
e[x].fa = z;
if (z != -1)
{
if (e[z].left == y)
e[z].left = x;
else
e[z].right = x;
}
e[x].right = y;
e[y].fa = x;
update(y);
update(x);
}

void turnl(int x)
{
int y = e[x].fa;
int z = e[y].fa;
e[y].right = e[x].left;
if (e[x].left != -1)
e[e[x].left].fa = y;
e[x].fa = z;
if (z != -1)
{
if (e[z].left == y)
e[z].left = x;
else
e[z].right = x;
}
e[x].left = y;
e[y].fa = x;
update(y);
update(x);
}

void splay(int x)
{
while (e[x].fa != -1)
{
int y = e[x].fa;
int z = e[y].fa;
if (z == -1)
{
if (x == e[y].left)
turnr(x);
else
turnl(x);
}
else
{
if (e[z].left == y && e[y].left == x)
{
turnr(y);
turnr(x);
}
else
{
if (e[z].right == y && e[y].right == x)
{
turnl(y);
turnl(x);
}
else
{
if (e[z].left == y && e[y].right == x)
{
turnl(x);
turnr(x);
}
else
{
turnr(x);
turnl(x);
}
}
}
}
}
root = x;
}

int find(int x)
{
int p = root;
while (p != -1)
{
if (e[p].v == x)
return p;
if (x < e[p].v)
p = e[p].left;
else
p = e[p].right;
}
return p;
}

void del(int x)
{
int p = find(x);
splay(p);
if (e[p].cnt > 1)
{
e[p].cnt--;
update(p);
return;
}
if (e[p].left == -1 && e[p].right == -1)
{
root = -1;
return;
}
if (e[p].left == -1)
{
root = e[p].right;
e[e[p].right].fa = -1;
return;
}
if (e[p].right == -1)
{
root = e[p].left;
e[e[p].left].fa = -1;
return;
}
int j = e[p].left;
while (e[j].right != -1)
j = e[j].right;
splay(j);
e[j].right = e[p].right;
e[e[p].right].fa = j;
update(j);
}

void insert(int x,int y)
{
if (e[y].v == x)
{
e[y].cnt++;
splay(y);
update(y);
return;
}
if (x < e[y].v)
{
if (e[y].left == -1)
{
e[y].left = ++tot;
e[tot].left = e[tot].right = -1;
e[tot].v = x;
e[tot].fa = y;
e[tot].cnt = 1;
sizee[tot] = 1;
return;
}
else
insert(x,e[y].left);
}
else
{
if (e[y].right == -1)
{
e[y].right = ++tot;
e[tot].left = e[tot].right = -1;
e[tot].v = x;
e[tot].fa = y;
e[tot].cnt = 1;
sizee[tot] = 1;
return;
}
insert(x,e[y].right);
}
update(y);
}

int query(int x)
{
int p = root,res = 0;
while (p != -1)
{
if (x < e[p].v)
p = e[p].left;
else
{
res += getsize(e[p].left);
if (x == e[p].v)
return res + 1;
res += e[p].cnt;
p = e[p].right;
}
}
return res;
}

int query2(int x)
{
int p = root;
while (p != -1)
{
if (e[p].left && x <= sizee[e[p].left])
p = e[p].left;
else
{
int temp = getsize(e[p].left) + e[p].cnt;
if (x <= temp)
return e[p].v;
x -= temp;
p = e[p].right;
}
}
return p;
}

int findl(int x)
{
int p = root,maxx = 0x7fffffff,cur = x;
while (p != -1)
{
if (e[p].v < x && x - e[p].v < maxx)
{
maxx = x - e[p].v;
cur = e[p].v;
}
if (x <= e[p].v)
p = e[p].left;
else
p = e[p].right;
}
return cur;
}

int findr(int x)
{
int p = root,maxx = 0x7fffffff,cur = x;
while (p != -1)
{
if(e[p].v > x && e[p].v - x < maxx)
{
maxx = e[p].v - x;
cur = e[p].v;
}
if (x >= e[p].v)
p = e[p].right;
else
p = e[p].left;
}
return cur;
}

int main()
{
scanf("%d",&n);
root = -1;
for (int i = 1; i <= n; i++)
{
int opt,x;
scanf("%d%d",&opt,&x);
if (opt == 1)
{
if (root == -1)
{
root = ++tot;
e[tot].left = e[tot].right = e[tot].fa = -1;
e[tot].cnt = 1;
e[tot].v = x;
sizee[tot] = 1;
}
else
insert(x,root);
splay(tot);
update(tot);
}
if (opt == 2)
del(x);
if (opt == 3)
printf("%d\n",query(x));
if (opt == 4)
printf("%d\n",query2(x));
if (opt == 5)
printf("%d\n",findl(x));
if (opt == 6)
printf("%d\n",findr(x));
}

return 0;
}

posted @ 2018-01-10 23:16  zbtrs  阅读(161)  评论(0编辑  收藏  举报