[LUOGU] P1801 黑匣子_NOI导刊2010提高(06)

Black Box是一种原始的数据库。它可以储存一个整数数组,还有一个特别的变量i。最开始的时候Black Box是空的.而i等于0。这个Black Box要处理一串命令。

命令只有两种:

ADD(x):把x元素放进BlackBox;

GET:i加1,然后输出Blackhox中第i小的数。

记住:第i小的数,就是Black Box里的数的按从小到大的顺序排序后的第i个元素。例如:

我们来演示一下一个有11个命令的命令串。(如下图所示)

(我是图)

现在要求找出对于给定的命令串的最好的处理方法。ADD和GET命令分别最多200000个。现在用两个整数数组来表示命令串:

1.A(1),A(2),…A(M):一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数,M$200000。例如上面的例子就是A=(31,一428,-10002)。

2.u(1),u(2),…u(N):表示第u(j)个元素被放进了Black Box里后就出现一个GET命令。例如上面的例子中u=(l,266)。输入数据不用判错。

输入输出格式
输入格式:
第一行,两个整数,M,N。

第二行,M个整数,表示A(l)

……A(M)。

第三行,N个整数,表示u(l)

…u(N)。

输出格式:
输出Black Box根据命令串所得出的输出串,一个数字一行。

输入输出样例
输入样例#17 4
3 1 -4 2 8 -1000 2
1 2 6 6
输出样例#13
3
1
2
说明
对于30%的数据,M≤10000;

对于50%的数据,M≤100000:

对于100%的数据,M≤200000

残缺的平衡树,局部变量!!

#include<iostream>
#include<cstdio>

using namespace std;

const int MAXN=200005;

inline int rd() {
    int ret=0,f=1;
    char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

int n,m;
int que[MAXN],data[MAXN];

int val[MAXN],siz[MAXN],cnt[MAXN];
int ch[MAXN][2],fa[MAXN];
int root,tot;
inline bool check(int x) {
    return x==ch[fa[x]][1];
}
inline void pushup(int x) {
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x];
};
inline int newnode(int x) {
    val[++tot]=x;
    siz[tot]=cnt[tot]=1;
    return tot;
}
void rotate(int x) {
    int y=fa[x],z=fa[fa[x]];
    bool ck=check(x);
    fa[ch[x][ck^1]]=y;
    ch[y][ck]=ch[x][ck^1];
    ch[x][ck^1]=y;
    fa[y]=x;
    fa[x]=z;
    if(z) ch[z][ch[z][1]==y]=x;
    pushup(y);
    pushup(x);
}
void splay(int x) {
    for(int f=fa[x]; f; rotate(x),f=fa[x])
        if(fa[f]) rotate(check(x)==check(f)?f:x);
    root=x;
}
bool insert(int x) {
    if(!root) return root=newnode(x),0;
    int cur=root,f=0;
    while(1) {
        if(val[cur]==x) {
            cnt[cur]++;
            pushup(cur);
            pushup(f);
            splay(cur);
            return 0;
        }
        f=cur;
        cur=ch[cur][x>val[cur]];
        if(!cur) {
            cur=newnode(x);
            fa[cur]=f;
            ch[f][x>val[f]]=cur;
            pushup(f);
            splay(cur);
            return 0;
        }
    }
}


int kth(int x) {
    int cur=root;
    while(1) {
        if(x<=siz[ch[cur][0]]) cur=ch[cur][0];
        else {
            x-=siz[ch[cur][0]]+cnt[cur];
            if(x<=0) return val[cur];
            cur=ch[cur][1];
        }
    }
}

int main() {
    n=rd();
    m=rd();
    int k=0,x;//
    for(int i=1; i<=n; i++) data[i]=rd();
    for(int i=1; i<=m; i++) x=rd(),que[x]++;
    for(int i=1; i<=n; i++) {
        insert(data[i]);
        while(que[i]--) {
            printf("%d\n",kth(++k));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/gh0stcai/article/details/80700409