題目鏈接:Dynamic Rankings
樹狀數組套主席樹版本的已經寫過了,現在就寫一個整體二分的。
注意把最初的序列也當成操作就好了。
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=4e5+10;
int n,m,cnt,res[N],a[N],idx,d[N];
struct node{int op,l,r,k,id;}t[N],tl[N],tr[N];
inline void insert(int x,int v){for(;x<=n;x+=x&(-x)) d[x]+=v;}
inline int ask(int x){int s=0; for(;x;x-=x&(-x)) s+=d[x]; return s;}
void solve(int l,int r,int x,int y){
if(l==r){for(int i=x;i<=y;i++) if(t[i].id) res[t[i].id]=l; return ;}
int mid=l+r>>1,fl=0,fr=0,cl=0,cr=0;
for(int i=x;i<=y;i++){
if(t[i].op==0){
if(t[i].k<=mid) insert(t[i].l,t[i].r),tl[++cl]=t[i];
else tr[++cr]=t[i];
}else{
int num=ask(t[i].r)-ask(t[i].l-1);
if(num>=t[i].k) fl=1,tl[++cl]=t[i];
else fr=1,tr[++cr]=t[i],tr[cr].k-=num;
}
}
for(int i=x;i<=y;i++) if(t[i].op==0&&t[i].k<=mid) insert(t[i].l,-t[i].r);
for(int i=1;i<=cl;i++) t[x+i-1]=tl[i];
for(int i=1;i<=cr;i++) t[x+cl+i-1]=tr[i];
if(fl) solve(l,mid,x,x+cl-1);
if(fr) solve(mid+1,r,x+cl,y);
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i],t[++cnt]={0,i,1,a[i],0};
for(int i=1,x,y,k;i<=m;i++){
char d; cin>>d>>x>>y;
if(d=='C') t[++cnt]={0,x,-1,a[x],0},t[++cnt]={0,x,1,y,0},a[x]=y;
else cin>>k,t[++cnt]={1,x,y,k,++idx};
}
solve(0,1e9,1,cnt);
for(int i=1;i<=idx;i++) cout<<res[i]<<'\n';
return 0;
}