网址:https://www.luogu.org/problem/P2343
题意:
维护一个支持$O(logn)$插入和查询第$k$大的数据结构。
题解:
只要是平衡树都行。这里我们使用splay,抄个板子即可。
AC代码:
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 5; struct Splay { int fa[MAXN], val[MAXN], son[MAXN][2], size[MAXN], num[MAXN]; int sz, rt; void init() { rt = sz = 0; } bool getson(int x) { return son[fa[x]][1] == x; } void con(int x, int y, int z) { if (x) fa[x] = y; if (y) son[y][z] = x; } void up(int x) { if (x) { size[x] = num[x]; if (son[x][0]) size[x] += size[son[x][0]]; if (son[x][1]) size[x] += size[son[x][1]]; } } void rotate(int x) { int fx = fa[x], ffx = fa[fx]; int fs = getson(x), ffs = getson(fx); con(son[x][fs ^ 1], fx, fs); con(fx, x, fs ^ 1); con(x, ffx, ffs); up(fx), up(x); } void splay(int x, int end) { end = fa[end]; int f; while (fa[x] != end) { f = fa[x]; if (fa[f] != end) rotate(getson(x) == getson(f) ? f : x); rotate(x); } if (!end) rt = x; } int newnode(int x, int f) { int root = ++sz; fa[root] = f; son[f][x > val[f]] = root; son[root][0] = son[root][1] = 0; size[root] = num[root] = 1; val[root] = x; return root; } void insert(int x) { if (!rt) { rt = newnode(x, 0); return; } int now = rt, f = 0; while (1) { if (x == val[now]) { ++num[now]; up(now), up(f); splay(now, rt); return; } f = now, now = son[now][x > val[now]]; if (!now) { int tmp = newnode(x, f); up(f); splay(tmp, rt); return; } } } int querynum(int rnk) { int now = rt; while (1) { if (son[now][1] && rnk <= size[son[now][1]]) { now = son[now][1]; continue; } if (son[now][1]) rnk -= size[son[now][1]]; if (rnk <= num[now]) { splay(now, rt); return now; } rnk -= num[now]; now = son[now][0]; } } }; Splay sp; const int MAXBUF = 1 << 20; char buf[1 << 20], * fh = NULL, * ft = NULL; inline char gc() { if (fh == ft) { int l = fread(buf, 1, MAXBUF, stdin); ft = (fh = buf) + l; } return *fh++; } inline int read() { int x = 0; char c = gc(); for (; c < '0' || c > '9'; c = gc()) ; for (; c >= '0' && c <= '9'; c = gc()) x = (x << 3) + (x << 1) + c - '0'; return x; } inline void _write(long long x) { if (x > 9) _write(x / 10); putchar(x % 10 + '0'); } inline void write(long long x) { _write(x); putchar('\n'); } int main() { sp.init(); int n, m, a, op; //scanf("%d%d", &n, &m); n = read(), m = read(); for (int i = 0; i < n; ++i) { //scanf("%d", &a); a = read(); sp.insert(a); } for (int i = 0; i < m; ++i) { //scanf("%d%d", &op, &a); op = read(), a = read(); if (op == 1) printf("%d\n", sp.val[sp.querynum(a)]); else if (op == 2) sp.insert(a); } return 0; }