[洛谷P3834] 【模板】可持久化线段树 1(主席树)

题目大意:静态区间第K小

题解:主席树

卡点:

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 200010
#define maxm 12000010
using namespace std;
int rt[maxn], lc[maxm], rc[maxm], num[maxm], idx;
int n, m, x, y, k;
int s[maxn], rnk[maxn], p[maxn];
inline bool cmp (int a,int b){return s[a] < s[b];}

void add(int &cur, int ver, int l, int r, int x) {
	cur = ++idx;
	lc[cur] = lc[ver]; rc[cur] = rc[ver], num[cur] = num[ver] + 1;
	if (l ^ r) {
		int mid = l + r >> 1;
		if (x <= mid) add(lc[cur], lc[ver], l, mid, x);
		else add(rc[cur], rc[ver], mid + 1, r, x);
	}
} 
int ask(int L, int R, int l, int r, int k) {
	if (l == r) return s[rnk[l]]; 
	int t = num[lc[R]] - num[lc[L]], mid = l + r >> 1;
	if (k <= t) return ask(lc[L], lc[R], l, mid, k);
	else return ask(rc[L], rc[R], mid + 1, r, k - t);
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)scanf("%d", &s[i]), rnk[i] = i;
	sort(rnk + 1, rnk + n + 1, cmp);
	for (int i = 1; i <= n; i++) p[rnk[i]] = i;
	for (int i = 1; i <= n; i++) rt[i] = rt[i - 1], add(rt[i], rt[i - 1], 1, n, p[i]);
	while (m--) {
		scanf("%d%d%d", &x, &y, &k);
		printf("%d\n", ask(rt[x - 1], rt[y], 1, n, k));
	}
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/Memory-of-winter/p/9332231.html
今日推荐