Loading

[可持久化权值线段树] [模板] [数组版本]

[可持久化权值线段树] [模板] [数组版本]

\[1 \leq n \leq 2e5\\ |a_i| \leq 1e9 \]

感觉动态开点用指针好理解一点

但是太难调试了,还是数组版本吧

代码

int a[maxn],b[maxn],len;

inline int getid(int val){
	return lower_bound(b + 1,b + len + 1,val) - b;
}

struct ZXS{
	int cnt;
	vector<int> sum,L,R,T;
	ZXS(int n):cnt(0),sum(n * 40),L(n * 40),R(n * 40),T(n + 5) {}
	
	int build(int l,int r){
		int rt = ++cnt;
		sum[rt] = 0;
		int mid = l + r >> 1;
		if(l < r) {
			L[rt] = build(l,mid);
			R[rt] = build(mid + 1,r);
		}
		return rt;
	}
	
	int update(int pre,int l,int r,int x){
		int rt = ++cnt;
		L[rt] = L[pre],R[rt] = R[pre];
		sum[rt] = sum[pre] + 1;
		int mid = l + r >> 1;
		if(l < r) {
			if(x <= mid) L[rt] = update(L[pre],l,mid,x);
			else R[rt] = update(R[pre],mid + 1,r,x);
		}
		return rt;
	}
	int query(int lt,int rt,int l,int r,int k) {
		if(l >= r) return l;
		int x = sum[L[rt]] - sum[L[lt]];
		int mid = l + r >> 1;
		if(x >= k) return query(L[lt],L[rt],l,mid,k);
		else return query(R[lt],R[rt],mid + 1,r,k - x);
	}
};

int main(){
	int n = rd();
	int q = rd();
	for(int i = 1;i <= n;i++) {
		a[i] = rd();
		b[i] = a[i];
	}
	sort(b + 1,b + n + 1);
	len = unique(b + 1,b + n + 1) - (b + 1);
	
	ZXS seg(n);
	seg.T[0] = seg.build(1,len);
	for(int i = 1;i <= n;i++){
		seg.T[i] = seg.update(seg.T[i - 1],1,len,getid(a[i]));
	} 
	while(q--){
		int l = rd();
		int r = rd();
		int k = rd();
		printf("%d\n",b[seg.query(seg.T[l - 1],seg.T[r],1,len,k)]);
	}
}
	
posted @ 2021-03-06 10:20  MQFLLY  阅读(65)  评论(0编辑  收藏  举报