洛谷 P2343 宝石管理系统

徘徊边缘 提交于 2019-11-26 14:21:40

洛谷 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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!