题解 P2617 【Dynamic Ranking】
I_AM_HelloWord · · 题解
光说树状数组套主席树对于初学者是很难理解的,比如蒟蒻我。
但是我觉得这种做法的核心思想就是类比像用优化动态前缀和,我们规定root[i]维护的是[i-lowbit(i),i]这段区间的主席树,而不是静态主席那样维护[1..i],由于洛谷空间卡的松,直接弄弄就行了,不需要其他的优化。
如果你还是不太清楚,可以看看这篇博客,我觉得写的还不错:http://blog.csdn.net/no1\_terminator/article/details/77606822
参考代码(嗯【手动害羞⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄】,高仿楼下dalao):
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=10100;
int n,m,totx,toty,tn,T_cnt=1;
struct TreeNode{
int L,R,sum;
}T[N*600];
int x[N],y[N],root[N],ql[N],qr[N],qt[N],a[N],b[N<<1];
char s[10];
int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
void insert(int &now,int x,int index,int l=1,int r=tn){
T[T_cnt++]=T[now];now=T_cnt-1;
T[now].sum+=index;
if (l==r)return;
int mid=(l+r)>>1;
if (x<=mid)insert(T[now].L,x,index,l,mid);
else insert(T[now].R,x,index,mid+1,r);
}
void add(int x,int index){
int pos=lower_bound(b+1,b+tn+1,a[x])-b;
for (int i=x;i<=n;i+=i&(-i))
insert(root[i],pos,index);
}
int query(int k,int l=1,int r=tn){
if (l==r)return l;
int sum=0,mid=(l+r)>>1;
for (int i=1;i<=totx;i++)sum-=T[T[x[i]].L].sum;
for (int i=1;i<=toty;i++)sum+=T[T[y[i]].L].sum;
if (k<=sum){
for (int i=1;i<=totx;i++)x[i]=T[x[i]].L;
for (int i=1;i<=toty;i++)y[i]=T[y[i]].L;
return query(k,l,mid);
}else{
for (int i=1;i<=totx;i++)x[i]=T[x[i]].R;
for (int i=1;i<=toty;i++)y[i]=T[y[i]].R;
return query(k-sum,mid+1,r);
}
}
int main(){
n=read(),m=read();
for (int i=1;i<=n;i++)
b[i]=a[i]=read();
tn=n;
for (int i=1;i<=m;i++){
scanf("%s",s);
ql[i]=read(),qr[i]=read();//s='Q' ql->l,qr->r,qt->k s='C' ql->x qr->k
if (s[0]=='Q')qt[i]=read();
else b[++tn]=qr[i];
}
sort(b+1,b+tn+1);
tn=unique(b+1,b+tn+1)-b-1;
for (int i=1;i<=n;i++)add(i,1);
for (int i=1;i<=m;i++){
if (qt[i]){
totx=toty=0;
for (int j=ql[i]-1;j;j-=j&(-j))x[++totx]=root[j];
for (int j=qr[i];j;j-=j&(-j))y[++toty]=root[j];
printf("%d\n",b[query(qt[i])]);
}else{
add(ql[i],-1);
a[ql[i]]=qr[i];
add(ql[i],1);
}
}
return 0;
}