[洛谷P1801]黑匣子_NOI导刊2010提高(06)
题目大意:两个操作:向一个可重集中加入一个元素;询问第$k$大的数($k$为之前询问的个数加一)
题解:离散化,权值线段树直接查询
卡点:无
C++ Code:
#include <cstdio> #include <algorithm> #define maxn 200010 int s[maxn], v[maxn]; int ret[maxn]; int n, m; int V[maxn << 2]; void add(int rt, int l, int r, int pos) { V[rt]++; if (l == r) return ; int mid = l + r >> 1; if (pos <= mid) add(rt << 1, l, mid, pos); else add(rt << 1 | 1, mid + 1, r, pos); } int ask(int rt, int l, int r, int sz) { if (l == r) return l; int mid = l + r >> 1; if (sz <= V[rt << 1]) return ask(rt << 1, l, mid, sz); else return ask(rt << 1 | 1, mid + 1, r, sz - V[rt << 1]); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", s + i); v[i] = s[i]; } int tot = (std::sort(v + 1, v + n + 1), std::unique(v + 1, v + n + 1) - v - 1); for (int i = 1; i <= n; i++) { int tmp = s[i]; s[i] = std::lower_bound(v + 1, v + tot + 1, tmp) - v; ret[s[i]] = tmp; } int last = 1; for (int i = 1, x; i <= m; i++) { scanf("%d", &x); for (; last <= x; last++) add(1, 1, n, s[last]); printf("%d\n", ret[ask(1, 1, n, i)]); } return 0; }