[洛谷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;
}

  

猜你喜欢

转载自www.cnblogs.com/Memory-of-winter/p/9860776.html