#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int tot,n,m,ver[maxn],a[maxn],b[maxn<<1];
int ndr[maxn],ndl[maxn],cntr,cntl,len;
//可能m个全改,所以+maxn,即<<1
struct tt{
int l,r,val;
//val是出现次数
}tree[maxn<<9];
//(log n)^2
struct ss{
char id[3];
int x,y,z;
}c[maxn];
int build(int l,int r){
int rt=++tot;
tree[rt].val=0;
tree[rt].l=rt;
tree[rt].r=rt;
return rt;
}
void pushup(int root){
tree[root].val=tree[tree[root].l].val+tree[tree[root].r].val;
}
int update(int node,int l,int r,int pos,int val){
int root=++tot;
tt &rt=tree[root];
rt=tree[node];
if(l==r){
rt.val+=val;
return root;
}
int mid=(l+r)>>1;
if(pos<=mid) rt.l=update(rt.l,l,mid,pos,val);
else rt.r=update(rt.r,mid+1,r,pos,val);
pushup(root);
return root;
}
//p位置出现x或删去x
void add(int x,int p,int cs){
x=lower_bound(b+1,b+1+len,x)-b;
//树状数组的各个下标是从1~n即n个状态,所以p的边界不是len
for(;p<=n;p+=p&-p)//p往上走找数组数组要更新的各位置 (状态)
ver[p]=update(ver[p],1,len,x,cs);
}
//求左边部分所有出现次数
int sum(int node[],int cnt){
int ans=0;
for(int i=1;i<=cnt;i++)//
ans+=tree[tree[node[i]].l].val;
//求左边的前缀和 所以.l
return ans;
}
int query(int l,int r,int k){
if(l==r) return l;
//查询区间右-左,即lst的 - pre的
int tx=sum(ndr,cntr)-sum(ndl,cntl);
int mid=(l+r)>>1;
//够了就只看左子树,所以查询的左右边界,也只看左子树即ndlr都往左子树移
if(tx>=k){
for(int i=1;i<=cntl;i++) ndl[i]=tree[ndl[i]].l;
for(int i=1;i<=cntr;i++) ndr[i]=tree[ndr[i]].l;
return query(l,mid,k);
}
else {
for(int i=1;i<=cntl;i++) ndl[i]=tree[ndl[i]].r;
for(int i=1;i<=cntr;i++) ndr[i]=tree[ndr[i]].r;
return query(mid+1,r,k-tx);
}
}
int ask(int l,int r,int k){
//定义过全局了,这里也不能再定义。直接赋值即可,否则cntl,cntr更新完的值传不到全局,用不了
cntl=cntr=0;
//查询区间的左边界,即pre
for(int p=l;p>0;p-=p&-p) ndl[++cntl]=ver[p];
//查询区间的右边界,即lst
for(int p=r;p>0;p-=p&-p) ndr[++cntr]=ver[p];
return query(1,len,k);
}
int main(){
int x,l,r,k;//len开了全局,main里面不能再定义一遍len
tot=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
len=n;
for(int i=1;i<=m;i++){
scanf("%s%d%d",c[i].id,&c[i].x,&c[i].y);
if(c[i].id[0]=='C') b[++len]=c[i].y;
else scanf("%d",&c[i].z);
}
sort(b+1,b+1+len);
len=unique(b+1,b+1+len)-(b+1);
// memset(ver,0,sizeof(ver));
ver[0]=build(1,len);
for(int i=1;i<=n;i++){
add(a[i],i,1);
}
for(int i=1;i<=m;i++){
if(c[i].id[0]=='Q')
printf("%d\n",b[ask(c[i].x-1,c[i].y,c[i].z)]);
else if(a[c[i].x]!=c[i].y){
add(a[c[i].x],c[i].x,-1);
add(c[i].y,c[i].x,1);
a[c[i].x]=c[i].y;
//树里改完之后,a数组也要改。因为在下一次改的时候要看a的值 即判断a[c[i].x]!=c[i].y
}
}
return 0;
}
洛谷P1627
猜你喜欢
转载自blog.csdn.net/weixin_50904510/article/details/120035159
今日推荐
周排行