[luogu P2617] Dynamic Rankings

题目大意:

带修区间第K小

 

题解:
这是道很模板的题目,基本思路就是树状数组套主席树。

首先对于主席树来讲是只支持静态区间第k小的,同样基于做差的思想,用树状数组维护动态开点的权值线段树,然后就行了。

看代码容易懂

 

Code:

#include<bits/stdc++.h>
#define N 200005
#define lowbit(x) (x & -x)
using namespace std;
int root[N], size[N * 600], ch[N * 600][2], tot, sz;
void add(int &rt, int l, int r, int x, int o){ //主席树建树
	if(!rt) rt = ++ sz;// 动态开点
	size[rt] += o;//因为不用保存历史版本,所以直接改
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(x <= mid) add(ch[rt][0], l, mid, x, o);
	else add(ch[rt][1], mid + 1, r, x, o);
}
int a[N], b[N], sx, sy, xx[N], yy[N], n;
void update(int x, int y){//树状数组维护前缀和,每个点表示的是 i - lowbit(i) + 1 ~ i的数 组成的权值线段树
	int k = lower_bound(b + 1, b + 1 + tot, a[x]) - b;
	for(; x <= n; x += lowbit(x)) add(root[x], 1, tot, k, y);
}
int query(int l, int r, int x){//询问,就是权值线段树上二分(多颗)
	if(l == r) return l;
	int sum = 0, mid = (l + r) >> 1;
	for(int i = 1; i <= sx; i ++) sum -= size[ch[xx[i]][0]];
	for(int i = 1; i <= sy; i ++) sum += size[ch[yy[i]][0]];
	if(x <= sum){
		for(int i = 1; i <= sx; i ++) xx[i] = ch[xx[i]][0];
		for(int i = 1; i <= sy; i ++) yy[i] = ch[yy[i]][0];	
		return query(l, mid, x);
	}else{
		for(int i = 1; i <= sx; i ++) xx[i] = ch[xx[i]][1];
		for(int i = 1; i <= sy; i ++) yy[i] = ch[yy[i]][1];	
		return query(mid + 1, r, x - sum);
	}
}
char c[N];
int m, l[N], r[N], k[N];
int main(){
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++){
		scanf("%d", &a[i]);
		b[++ tot] = a[i];
	}
	for(int i = 1; i <= m; i ++){
		scanf(" %c", &c[i]);
		if(c[i] == 'Q')	scanf("%d%d%d", &l[i], &r[i], &k[i]);
		else scanf("%d%d", &l[i], &r[i]), b[++ tot] = r[i];
	}
	sort(b + 1, b + 1 + tot);
	tot = unique(b + 1, b + 1 + tot) - b - 1;//xjb离散化
 
	for(int i = 1; i <= n; i ++) update(i, 1);
	for(int i = 1; i <= m; i ++){
		if(c[i] == 'C'){
			update(l[i], -1);
			a[l[i]] = r[i];
			update(l[i], 1);
		}else{
			sx = sy = 0;
			for(int j = l[i] - 1; j; j -= lowbit(j)) xx[++ sx] = root[j];
			for(int j = r[i]; j; j -= lowbit(j)) yy[++ sy] = root[j];	// 先记下需要用的每颗权值线段树的根,方便树上二分。
			printf("%d\n", b[query(1, tot, k[i])]);//输出
		}
	}
	return 0;
}

.......

posted @ 2019-03-19 16:45  lahlah  阅读(23)  评论(0编辑  收藏  举报