主席树-可持久化线段树学习笔记

可持久化版本的线段树

支持对历史版本的一些操作

每个版本对应一个根

这样也就相当于每个版本有一棵线段树

有信息被更改的节点就新建一个

没有则与原来的共用

线段树用来维护出现次数,所以一般都用到离散化

有了每个数字出现次数自然就可以查第 k 大了

那么区间第 k 大呢?

其实主席树大概是一个前缀和套线段树的数据结构

这样利用前缀和算出区间内出现次数

也就可以得出区间第 k 大了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
#include<cmath>
using namespace std;

const int MAXN = 200001;

struct Node{
	int ls, rs, sum;
	Node(){ls = rs = sum = 0;}
}t[MAXN << 5];
int n, m, sizb, poolcur;
int a[MAXN], b[MAXN], rnk[MAXN], Root[MAXN << 5];

inline int rd() {
	register int x = 0;
	register char c = getchar();
	register bool f = false;
	while(!isdigit(c)) {
		if(c == '-') f = true;
		c = getchar();
	}
	while(isdigit(c)) {
		x = x * 10 + c - 48;
		c = getchar();
	}
	return f ? -x : x;
}
int build(int l, int r) {
	int cur = ++poolcur;
	if(l == r) return cur;
	int mid = ((l + r) >> 1);
	t[cur].ls = build(l, mid);
	t[cur].rs = build(mid + 1, r);
	return cur;
}
int Insert(int l, int r, int cur, int dst) {
	int newcur = ++poolcur;
	t[newcur] = t[cur];
	++t[newcur].sum;
	if(l == r) return newcur;
	int mid = ((l + r) >> 1);
	if(dst <= mid) t[newcur].ls = Insert(l, mid, t[cur].ls, dst);
	else t[newcur].rs = Insert(mid + 1, r, t[cur].rs, dst);
	return newcur;
}
int query(int x, int y, int l, int r, int k) {
	if(l == r) return l;
	int lsiz = t[t[y].ls].sum - t[t[x].ls].sum;
	int mid = ((l + r) >> 1);
	if(k <= lsiz) return query(t[x].ls, t[y].ls, l, mid, k);
	else return query(t[x].rs, t[y].rs, mid + 1, r, k - lsiz);
}
inline void init() {
	sort(b + 1, b + n + 1);
	sizb = unique(b + 1, b + n + 1) - b - 1;
	for(int i = 1; i <= n; ++i) rnk[i] = lower_bound(b + 1, b + sizb + 1, a[i]) - b;
	return;
}

int main() {
	n = rd(); m = rd();
	for(int i = 1; i <= n; ++i) a[i] = b[i] = rd();
	init();
	Root[0] = build(1, sizb);
	for(int i = 1; i <= n; ++i) Root[i] = Insert(1, sizb, Root[i - 1], rnk[i]);
	int l, r, k;
	while(m--) {
		l = rd(); r = rd(); k = rd();
		printf("%d\n", b[query(Root[l - 1], Root[r], 1, sizb, k)]);
	}
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/xcysblog/p/9069824.html