【BZOJ1901】【 ZOJ2112】- Dynamic Rankings(整体二分)

传送门

其实和前面那道K-th Number几乎一模一样吧

只需要在中途添加修改操作就可以了

注意由于整体二分的特殊性

修改操作要先将原来的贡献给排除掉在添加这一次操作的贡献

还有数组大小

具体看代码就可以了

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=400005;
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res*f;
}
struct ask{
	int l,r,k,pos,op;
}q[N],q1[N],q2[N];
int tr[N],ans[N],a[N],n,m,cnt,tot;
char c[5];
inline int lowbit(int x){
	return (x&-x);
}
inline void add(int pos,int k){
	for(;pos<=n;pos+=lowbit(pos))tr[pos]+=k;
}
inline int query(int pos,int res=0){
	for(;pos;pos-=lowbit(pos))res+=tr[pos];return res;
}
void solve(int l,int r,int st,int des){
	if(l>r||st>des)return;
	if(l==r){
		for(int i=st;i<=des;i++)if(q[i].op)ans[q[i].pos]=l;
		return;
	}
	int mid=(l+r)>>1,cnt1=0,cnt2=0;
	for(int i=st;i<=des;i++){
		if(q[i].op){
			int tmp=query(q[i].r)-query(q[i].l-1);
			if(tmp>=q[i].k)q1[++cnt1]=q[i];
			else q[i].k-=tmp,q2[++cnt2]=q[i];
		}
		else{
			if(q[i].l<=mid){
				q1[++cnt1]=q[i],add(q[i].pos,q[i].r);
			}
			else q2[++cnt2]=q[i]; 
		}
	}
    for(int i=1;i<=cnt1;i++) if(!q1[i].op) add(q1[i].pos, -q1[i].r);
    for(int i=1;i<=cnt1;i++) q[st+i-1]=q1[i];
    for(int i=1;i<=cnt2;i++) q[st+cnt1+i-1]=q2[i];
    solve(l, mid, st, st+cnt1-1); solve(mid+1, r, st+cnt1, des);
}
int main(){
	int T=read();
	while(T--){
		cnt=tot=0,memset(tr,0,sizeof(tr));
		n=read(),m=read();
		for(int i=1;i<=n;++i){
			a[i]=read();q[++cnt]=(ask){a[i],1,0,i,0};
		}
		for(int i=1;i<=m;i++){
			scanf("%s",c+1);
			if(c[1]=='Q'){
				int l=read(),r=read(),k=read();q[++cnt]=(ask){l,r,k,++tot,1};
			}
			else{
				int pos=read(),k=read();
				q[++cnt]=(ask){a[pos],-1,0,pos,0},q[++cnt]=(ask){a[pos]=k,1,0,pos,0};
			}
		}
		solve(-1e9,1e9,1,cnt);
		for(int i=1;i<=tot;i++)cout<<ans[i]<<'\n';
	}
}

posted @ 2019-01-13 20:07  Stargazer_cykoi  阅读(...)  评论(...编辑  收藏