【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';
}
}