洛谷 P2343 宝石管理系统
Description
- GY君购买了一批宝石放进了仓库。有一天GY君心血来潮,想要清点他的宝石,于是把m个宝石都取出来放进了宝石管理系统。每个宝石i都有一个珍贵值vi,他希望你能编写程序查找到从大到小第n珍贵的宝石。但是现在问题来了,他非常不小心的留了一些宝石在仓库里面,有可能要往现有的系统中添加宝石。这些宝石的个数比较少。他表示非常抱歉,但是还是希望你的系统能起作用。
Input
第一行一个整数m,q,表示已经取出来的宝石个数以及接下来的查询或插入操作个数。
第二行m个整数,表示这m个宝石的珍贵值。
以下q行,每行两个整数c,n,
若c=1(即询问),则输出当前第n珍贵的宝石,
若c=2(即插入),则往系统中插入珍贵值为n的宝石。
Output
- 对于每个c=1(询问),输出当前第n珍贵的宝石的珍贵值vi。
Sample Input
5 3 1 3 2 5 6 1 3 2 4 1 6
Sample Output
3
1
题解:
- 平衡树裸题。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define N 100000 + 30000 + 5
#define inf 0x7fffffff
using namespace std;
struct T {int l, r, cnt, size, val, dat;} t[N];
int n, q, root, tot, sum;
int read()
{
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x *= f;
}
int New(int val)
{
t[++tot].val = val, t[tot].dat = rand();
t[tot].size = t[tot].cnt = 1;
return tot;
}
void up(int p) {t[p].size = t[t[p].l].size + t[t[p].r].size + t[p].cnt;}
void zig(int &y)
{
int x = t[y].l;
t[y].l = t[x].r, t[x].r = y, y = x;
up(t[y].r), up(y);
}
void zag(int &x)
{
int y = t[x].r;
t[x].r = t[y].l, t[y].l = x, x = y;
up(t[x].l), up(x);
}
void insert(int &p, int val)
{
if(!p) {p = New(val); return;}
if(val == t[p].val) {t[p].cnt++, up(p); return;}
if(val < t[p].val)
{
insert(t[p].l, val);
if(t[t[p].l].dat > t[p].dat) zig(p);
}
else
{
insert(t[p].r, val);
if(t[t[p].r].dat > t[p].dat) zag(p);
}
up(p);
}
int valOfRank(int p, int rank)
{
if(!p) return inf;
if(t[t[p].l].size >= rank) return valOfRank(t[p].l, rank);
if(t[t[p].l].size + t[p].cnt >= rank) return t[p].val;
return valOfRank(t[p].r, rank - t[t[p].l].size - t[p].cnt);
}
int main()
{
New(inf), New(-inf), root = 1, t[1].l = 2, up(1);
n = read(), q = read(), sum = n;
for(int i = 1; i <= n; i++) insert(root, read());
for(int i = 1; i <= q; i++)
{
int op = read(), x = read();
if(op == 1) x = sum - x + 1, printf("%d\n", valOfRank(root, x + 1));
else if(op == 2) insert(root, x), sum++;
}
return 0;
}