洛谷 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; }