Dynamic Rankings
实际上就是将单个询问的二分修改为同时处理多个询问
考虑二分答案
对于每一个mid,考虑询问是归为[l,mid]或[mid+1,r]
统计修改的贡献,同样将修改归为[l,mid]或[mid+1,r]
#include <bits/stdc++.h>
#define INF 1e9
using namespace std;
const int MAXN=3e5+5;
int n,m;
int x;
int a[MAXN];
int ans[MAXN];
struct Query{
int op;
int l,r,key;
int pos,val;
}query[MAXN],lq[MAXN],rq[MAXN];
int Bit[MAXN];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
{
Bit[i]+=k;
}
return;
}
int Sum(int k)
{
int res=0;
for(int i=k;i>=1;i-=lowbit(i))
{
res+=Bit[i];
}
return res;
}
char s[105];
int l,r,k;
void solve(int lv,int rv,int st,int ed)//递归处理[l,r]可能的答案对[st,ed]的答案
{
if(st>ed)
{
return;
}
//printf("%d %dfuck\n",st,ed);
if(lv==rv)
{
for(int i=st;i<=ed;i++)
{
if(query[i].op>=1)
{
ans[query[i].op]=lv;
}
}//边界
return;
}
int mid=(lv+rv)>>1;
int lt=0;
int rt=0;
for(int i=st;i<=ed;i++)
{
if(query[i].op<=0)
{
if(query[i].val<=mid)
{
int xfg=query[i].op;
if(!xfg)
{
xfg++;
}
update(query[i].pos,xfg);
lq[++lt]=query[i];
//考虑小于mid的对询问的贡献
}
else
{
rq[++rt]=query[i];
}
}
else
{
int cg=(Sum(query[i].r)-Sum(query[i].l-1));
int rest=query[i].key-cg;
//如果rest>0,那么说明<mid的无法完全消耗排名
if(rest<=0)
{
lq[++lt]=query[i];
}
else
{
query[i].key=rest;
rq[++rt]=query[i];
}
}
}
for(int i=1;i<=lt;i++)
{
if(lq[i].op<=0)
{
int xfg=lq[i].op;
if(!xfg)
{
xfg++;
}
// printf("%d\n",lq[i].pos);
update(lq[i].pos,-xfg);//清空标记
}
}
int cnt_q=st-1;
for(int i=1;i<=lt;i++)
{
query[++cnt_q]=lq[i];
}
for(int i=1;i<=rt;i++)
{
query[++cnt_q]=rq[i];
}
solve(lv,mid,st,st+lt-1);
solve(mid+1,rv,st+lt,ed);//递归
}
int main() {
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
ans[i]=-1;
}
int cnt_query=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
a[i]=x;
query[++cnt_query].op=0;
query[cnt_query].val=x;
query[cnt_query].pos=i;
} //初始的值
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d %d %d",&l,&r,&k);
query[++cnt_query].op=i;
query[cnt_query].l=l;
query[cnt_query].r=r;
query[cnt_query].key=k;
}
else
{
scanf("%d %d",&k,&x);
query[++cnt_query].op=-1;
query[cnt_query].pos=k;
query[cnt_query].val=a[k];
a[k]=x;
query[++cnt_query].op=0;
query[cnt_query].pos=k;
query[cnt_query].val=a[k];
}//裁成两个修改
}
solve(0,INF,1,cnt_query);
for(int i=1;i<=m;i++)
{
// printf("%d\n",ans[i]);
if(ans[i]!=-1)
{
printf("%d\n",ans[i]);
}
}
}