题目描述

在 J 班的体育课上, 同学们常常会迟到几分钟, 但体育老师的点名却一直很准时.

老师只关心同学的身高, 他会依次询问当前最高的身高, 次高的身高, 第三高的身高, 等等. 在询问的过程中, 会不时地有人插进队伍里. 你需要回答老师每次的询问.

输入格式

第一行两个整数 \(n\)\(m\), 表示先后有 \(n\) 个人进队, 老师询问了 \(m\)

第二行 \(n\) 个整数, 第 \(i\) 个数 \(A_i\) 表示第 \(i\) 个进入队伍的同学的身高为 \(A_i\)

第三行 \(m\) 个整数, 第 \(j\) 个数 \(B_j\) 表示老师在第 \(B_j\) 个同学进入队伍后有一次询问

输出格式

\(m\) 行, 每行一个整数, 依次表示老师每次询问的答案. 数据保证合法.

样例输入

7 4
9 7 2 8 14 1 8
1 2 6 6

样例输出

9
9
7
8

样例解释

(9) {No. 1=9}; (9 7) {No. 2=9}; (9 7 2 8 14 1) {No. 3=7; No. 4=8}

数据范围

40% 的数据保证 \(n \leq 1000\)

100% 的数据保证 \(1 \leq m \leq n \leq 30000\);\(0 \leq A_i \lt 2^{32}\)

Explanation

暴力可以水 40 分.

如果要 100 分做法需要用 Treap 或 Splay 维护第 K 大值.

但是 Splay 调不出来啊~

所以就用了 @xmcp 的代码.

Source Code


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <vector>

using namespace std;
typedef long long lli;
const int maxn = 40010;
const lli infinit = 0x007f7f7f7f7f7f7fll;

/*
class SplayTree
{
public:
    int parent[maxn], ch[maxn][2], root, ncnt, n;
    int size[maxn];
    lli val[maxn];
    #define lc(_x) ch[_x][0]
    #define rc(_x) ch[_x][1]
    #define par(_x) parent[_x]
    int makenode(int q, lli v) {
        int p = ++ncnt; n++;
        lc(p) = rc(p) = 0;
        par(p) = q;
        size[p] = 1;
        val[p] = v;
        return p; }
    void rotate(int p) {
        int q = par(p), g = par(q), x = p == rc(q);
        // Relink connections
        ch[q][x] = ch[p][!x]; if (ch[q][x]) par(ch[q][x]) = q;
        ch[p][!x] = q, par(q) = p;
        par(p) = g; if (g) ch[g][rc(g) == q] = p;
        size[q] = size[lc(q)] + 1 + size[rc(q)];
        size[p] = size[lc(p)] + 1 + size[rc(p)];
        return ; }
    void splay(int p, int t) {
        for (int q = 0; (q = par(p)) && q != t; rotate(p))
            if (par(q) && par(q) != t)
                rotate((p == lc(q)) == (q == lc(par(q))) ? q : p);
        if (t == 0) root = p; }
    int pre(int p) {
        cout << "preing " << p << endl;
        if (!lc(p)) { while (p == lc(par(p))) p = par(p); p = par(p); }
        if  { p = lc(p); while (rc(p)) p = rc(p); }
        return p; }
    int find(int x) {
        int p = root;
        while (true) {
            if (size[lc(p)] >= x) {
                p = lc(p); continue;
            } x -= size[lc(p)];
            if (x == 1) return p; x -= 1;
            p = rc(p);
        } return root; }
    int locate(lli v) {
        int p = root;
        while (true) {
            if (v > val[p] && rc(p)) {
                p = rc(p); continue; }
            if (v == val[p]) return p;
            if (lc(p)) p = lc(p); else return p;
        } return root; }
    lli query(int x) {
        int m = n - 1 - x;
        return val[find(m + 1)]; }
    void dfs(int p)
    {
        if (!p) return ;
        printf("%d %d %d\n", par(p), p, p==rc(par(p)));
        dfs(lc(p));
        dfs(rc(p));
    }
    void dfstree(void)
    {
        dfs(root);
    }
    void insert(lli v) {
        int rp = locate(v), lp = pre(lp);
        cout << rp << ' ' << lp << "*\n";
        splay(rp, 0);
        splay(lp, root);
        int c = makenode(lp, v);
        rc(lp) = c;
        size[lp]++, size[rp]++;
        dfstree();
        return ; }
    void build_tree(void) {
        n = ncnt = 0;
        root = makenode(0, 0);
        rc(root) = makenode(root, infinit);
        par(rc(root)) = root;
        size[root]++; }
} st; */

#define $ if(0)

class XmcpsSplayTree
{
public:
    static const int _N=50007, _I=2147000000;
    int child[_N][2], parent[_N], size[_N];
    lli value[_N];
    int root, graphtop;
    int query[_N];
    int insvalue[_N];
    bool inserted;

    void build_tree(void) {
        root = 1, graphtop = 2;
        inserted = false;
    }
    int flag(int x) {
        return x[parent][child][1]==x;
    }
    void rotate(int self) {
        int flaj=flag(self),
            p=self[parent],
            pp=p[parent],
            ch=self[child][!flaj];
        /****/ self[parent]=pp;
        if(pp) pp[child][flag(p)]=self;
        /****/ p[parent]=self;
        /****/ self[child][!flaj]=p;
        if(ch) ch[parent]=p;
        /****/ p[child][flaj]=ch;
        p[size]=p[child][0][size]+p[child][1][size]+1;
    }
    void splay(int self) {
        int p,pp;
        while((p=self[parent])) {
            if((pp=p[parent]))
                rotate(flag(self)==flag(pp)?p:self);
            rotate(self);
        }
        root=self;
    }
    void insert__(lli val) {
        while(true) {
            int ch=root[child][root[value]<val];
            if(!ch) {
                ch=graphtop++;
                ch[value]=val;
                ch[child][0]=ch[child][1]=0;
                ch[parent]=root;
                ch[size]=1;
                root[child][root[value]<val]=ch;
                splay(ch);
                return;
            }
            root=ch;
        }
    }
    void insert(lli val) {
        if (!inserted) {
            root[value] = val;
            inserted = true;
            return ;
        }
        insert__(val);
    }
    lli queryf(int k)
    {
        // int target = root;
        $ printf("get %d\n",k);
        int self=root,szl;
        while((szl=self[child][0][size])!=k-1) {
            if(szl>k-1) {
                $ puts("goto left");
                self=self[child][0];
            }
            else {
                $ puts("goto right");
                self=self[child][1],
                    k-=szl+1;
            }
            $ printf("now size of left = %d\n",szl);
        }
        $ printf("value is %lld\n",self[value]);
        return self[value];
    }
} st;

int n, m;
lli ins[maxn];
vector<int> qry[maxn];

int main(int argc, char** argv)
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &ins[i]);
    for (int i = 1, a; i <= m; i++) {
        scanf("%d", &a);
        qry[a].push_back(i);
    }
    // Querying while inserting
    st.build_tree();
    for (int i = 1; i <= n; i++) {
        st.insert(ins[i]);
        for (unsigned int j = 0; j < qry[i].size(); j++)
            printf("%lld\n", st.queryf(qry[i][j]));
    }
    return 0;
}