P2617
题目描述
题解
树状数组套主席树,离散化数组记得多开几倍(调了一周)
思想其实很简单,就是
l
o
g
n
logn
logn个主席树一起修改,询问
代码
#include<bits/stdc++.h>
#define M 200010
using namespace std;
int read(){
int f=1,re=0;char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-'){f=-1,ch=getchar();}
for(;isdigit(ch);ch=getchar()) re=(re<<3)+(re<<1)+ch-'0';
return re*f;
}
struct tree{int l,r,sum;}tr[M*200];
struct data{int vis,l,r,k,pos,val;}q[M];
int n,m,tmp1[100],tmp2[100],cnt,cnt1,cnt2,rt[M],len,a[M],b[M],tot;
char s[10];
void update(int &k,int l,int r,int pos,int val){
if(!k) k=++cnt;tr[k].sum+=val;
if(l==r){return;}
int mid=(l+r)>>1;
if(pos<=mid) update(tr[k].l,l,mid,pos,val);
else update(tr[k].r,mid+1,r,pos,val);
//tr[k].sum=tr[tr[k].l].sum+tr[tr[k].r].sum;
}
int solve(int l,int r,int k){
if(l==r)return l;
int mid=(l+r)>>1,lsize=0;
for(int i=1;i<=cnt1;i++)lsize+=tr[tr[tmp1[i]].l].sum;
for(int i=1;i<=cnt2;i++)lsize-=tr[tr[tmp2[i]].l].sum;
if(k<=lsize){
for(int i=1;i<=cnt1;i++)tmp1[i]=tr[tmp1[i]].l;
for(int i=1;i<=cnt2;i++)tmp2[i]=tr[tmp2[i]].l;
return solve(l,mid,k);
}else{
for(int i=1;i<=cnt1;i++)tmp1[i]=tr[tmp1[i]].r;
for(int i=1;i<=cnt2;i++)tmp2[i]=tr[tmp2[i]].r;
return solve(mid+1,r,k-lsize);
}
}
int lowbit(int x){return x&(-x);}
int query(int l,int r,int k){
memset(tmp1,0,sizeof(tmp1));
memset(tmp2,0,sizeof(tmp2));
cnt1=cnt2=0;
for(int i=r;i;i-=lowbit(i)) tmp1[++cnt1]=rt[i];
for(int i=l-1;i;i-=lowbit(i)) tmp2[++cnt2]=rt[i];
return solve(1,len,k);
}
void add(int x,int val){
int pos=lower_bound(b+1,b+len+1,a[x])-b;
for(int i=x;i<=n;i+=lowbit(i)) update(rt[i],1,len,pos,val);
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++) b[++tot]=a[i]=read();
for(int i=1;i<=m;i++){
scanf("%s",s);
if(s[0]=='Q') q[i].vis=1,q[i].l=read(),q[i].r=read(),q[i].k=read();
else q[i].vis=0,q[i].pos=read(),q[i].val=b[++tot]=read();
}sort(b+1,b+tot+1);
len=unique(b+1,b+tot+1)-b-1;
for(int i=1;i<=n;i++) add(i,1);
for(int i=1;i<=m;i++){
if(!q[i].vis){
add(q[i].pos,-1);
a[q[i].pos]=q[i].val;
add(q[i].pos,1);
}else printf("%d\n",b[query(q[i].l,q[i].r,q[i].k)]);
}return 0;
}