# BZOJ1901 Dynamic Rankings 题解（离线分治+树状数组）

1.格式$Q\,i\,j\,k$，表示查询区间$[i,j]$中第$k$大的数.
2.格式$C\,i\,t$，表示把$a[i]$改成$t$.
$1\leq n,m\leq 10^4,0\leq a[i],t\leq 10^9$.

POJ2104的拓展.

#include<bits/stdc++.h>
using namespace std;

#define Abigail inline void
typedef long long LL;

const int N=10000,INF=1000000000;

char rc(){
char c=getchar();
for (;c<'A'||c>'Z';c=getchar());
return c;
}

int n,m,c[N+9],a[N+9];

void Add(int p,int v){if (!p) return;for (;p<=n;p+=p&-p) c[p]+=v;}
int Query(int p){int res=0;for (;p;p-=p&-p) res+=c[p];return res;}
int Query(int l,int r){return Query(r)-Query(l-1);}

struct question{
int opt,x,y,z,id;
question(int Opt=0,int X=0,int Y=0,int Z=0,int Id=0){opt=Opt;x=X;y=Y;z=Z;id=Id;}
}q[N*3+9],lq[N*3+9],rq[N*3+9];
int cq,ans[N+9];

void Divide(question *q,int L,int R,int h,int t){
if (h>t) return;
if (L==R){
for (int i=h;i<=t;++i)
if (!q[i].opt) ans[q[i].id]=L;
return;
}
int mid=L+R>>1,lt=0,rt=0,tmp;
for (int i=h;i<=t;++i)
if (q[i].opt){
if (q[i].y>mid) rq[++rt]=q[i];
}else{
tmp=Query(q[i].x,q[i].y);
if (q[i].z<=tmp) lq[++lt]=q[i];
else q[i].z-=tmp,rq[++rt]=q[i];
}
for (int i=h;i<=t;++i)
for (int i=1;i<=lt;++i) q[h+i-1]=lq[i];
for (int i=1;i<=rt;++i) q[h+lt+i-1]=rq[i];
Divide(q,L,mid,h,h+lt-1);
Divide(q,mid+1,R,h+lt,t);
}

Abigail into(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i){
scanf("%d",&a[i]);
q[++cq]=question(1,i,a[i],1,0);
}
char opt;
int x,y,z;
for (int i=1;i<=m;++i){
opt=rc();
if (opt=='C'){
scanf("%d%d",&x,&y);
q[++cq]=question(1,x,a[x],-1,0);
q[++cq]=question(1,x,y,1,0);
a[x]=y;
}else{
scanf("%d%d%d",&x,&y,&z);
q[++cq]=question(0,x,y,z,i);
}
ans[i]=-1;
}
}

Abigail work(){
Divide(q,0,INF,1,cq);
}

Abigail outo(){
for (int i=1;i<=m;++i)
if (ans[i]^-1) printf("%d\n",ans[i]);
}

int main(){
into();
work();
outo();
return 0;
}


©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客