主席树模板

区间第 \(k\)

\(Code\)

#include<cstdio>
#include<algorithm>
using namespace std;

const int N = 2e5;
int n , m , rt[N + 5] , ind[N + 5] , a[N + 5] , len , size;

struct segment{
	int ls , rs , sum;
}seg[(N << 5) + 5];

inline int read()
{
	int res = 0;
	char ch = getchar();
	while (ch < '0' || ch > '9') ch = getchar();
	while (ch >= '0' && ch <= '9') res = (res << 3) + (res << 1) + ch - '0' , ch = getchar();
	return res;
}

inline int build(int l , int r)
{
	int o = ++size;
	if (l == r) return o;
	int mid = (l + r) >> 1;
	seg[o].ls = build(l , mid) , seg[o].rs = build(mid + 1 , r);
	return o;
}

inline int update(int x , int l , int r , int rt)
{
	int o = ++size;
	seg[o].ls = seg[rt].ls , seg[o].rs = seg[rt].rs , seg[o].sum = seg[rt].sum + 1;
	if (l == r && l == x) return o;
	int mid = (l + r) >> 1;
	if (x <= mid) seg[o].ls = update(x , l , mid , seg[rt].ls);
	else seg[o].rs = update(x , mid + 1 , r , seg[rt].rs);
	return o;
}

inline int query(int x , int y , int l , int r , int k)
{
	if (l == r) return l;
	int mid = (l + r) >> 1 , node = seg[seg[y].ls].sum - seg[seg[x].ls].sum;
	if (node >= k) return query(seg[x].ls , seg[y].ls , l , mid , k);
	else return query(seg[x].rs , seg[y].rs , mid + 1 , r , k - node);
}

int main()
{
	n = read() , m = read();
	for(register int i = 1; i <= n; i++) a[i] = read() , ind[i] = a[i];
	sort(ind + 1 , ind + n + 1);
	len = unique(ind + 1 , ind + n + 1) - ind - 1;
	rt[0] = build(1 , len);
	for(register int i = 1; i <= n; i++)
	{
		int x = lower_bound(ind + 1 , ind + len + 1 , a[i]) - ind;
		rt[i] = update(x , 1 , len , rt[i - 1]);
	}
	int x , y , z;
	for(register int i = 1; i <= m; i++)
	{
		x = read() , y = read() , z = read();
		printf("%d\n" , ind[query(rt[x - 1] , rt[y] , 1 , len , z)]);
	}
}

\(update\) 写法

int size, rt[N];
struct segment{int ls, rs, s;}seg[N * 16];

void update(int &p, int pre, int l, int r, int v)
{
	p = ++size;
	seg[p] = seg[pre], seg[p].s = seg[pre].s + 1;
	if (l == r) return;
	int mid = (l + r) >> 1;
	if (v <= mid) update(seg[p].ls , seg[pre].ls, l, mid, v);
	else update(seg[p].rs, seg[pre].rs, mid + 1, r, v);
}

int query(int p, int pre, int l, int r, int v)
{
	int o = seg[p].s - seg[pre].s;
	if (!o) return 0;
	if (l == r) return o;
	int mid = (l + r) >> 1;
	if (v <= mid) return query(seg[p].ls, seg[pre].ls, l, mid, v); 
	return query(seg[p].rs, seg[pre].rs, mid + 1, r, v);
}
posted @ 2020-08-05 21:37  leiyuanze  阅读(70)  评论(0编辑  收藏  举报