思路:
1.用树套树实现log修改。
2.查询的时候,把我们需要的(或者说容纳了询问区间所有值的线段树)--即构成这颗,查询区间权值总和线段树,的根存起来,求第k小的时候再来计算这颗权值总和线段树的左子树的和,然后判断是否进入这颗权值总和线段树的左子树或者右子树。
ps:这里还有个离散化,离线处理所有操作,把涉及到的权值全部放进数组里,然后用二分返回离散化后的值。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
struct xdss
{
int l,r,cnt;
}xds[N*32*6];
struct opss1
{
char c;
int l,r,k;
int id,y;
}ops[N];
int root[N*32*6],pretree[N*32*6],curtree[N*32*6],val[N*2],a[N];
int n,m,cnt,idx,cnt2,cnt3;
int findid(int x)
{
return lower_bound(val+1,val+1+cnt,x)-val;
}
void motify(int &rt,int l,int r,int pos,int vall)
{
if(!rt) rt=++idx;
xds[rt].cnt+=vall;
if(l==r) return;
int mid=l+r>>1;
if(pos<=mid) motify(xds[rt].l,l,mid,pos,vall);
else motify(xds[rt].r,mid+1,r,pos,vall);
}
int query(int l,int r,int k)
{
if(l==r) return val[l];
int zsum=0;
for(int i=1;i<=cnt3;i++) zsum+=xds[xds[curtree[i]].l].cnt;
for(int i=1;i<=cnt2;i++) zsum-=xds[xds[pretree[i]].l].cnt;
int mid=l+r>>1;
if(k<=zsum)
{
for(int i=1;i<=cnt3;i++) curtree[i]=xds[curtree[i]].l;
for(int i=1;i<=cnt2;i++) pretree[i]=xds[pretree[i]].l;
return query(l,mid,k);
}
else
{
k-=zsum;
for(int i=1;i<=cnt3;i++) curtree[i]=xds[curtree[i]].r;
for(int i=1;i<=cnt2;i++) pretree[i]=xds[pretree[i]].r;
return query(mid+1,r,k);
}
}
int lowbit(int x){return x&-x;}
void szmotify(int id,int pos,int vall){for(int i=id;i<=n;i+=lowbit(i)) motify(root[i],1,cnt,pos,vall);}
int szquery(int pre,int cur,int k)
{
cnt2=cnt3=0;
for(int i=pre;i;i-=lowbit(i)) pretree[++cnt2]=root[i];
for(int i=cur;i;i-=lowbit(i)) curtree[++cnt3]=root[i];
// cout<<cnt2<<' '<<cnt3<<'\n';
return query(1,cnt,k);
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i],val[++cnt]=a[i];
for(int i=1;i<=m;i++)
{
char op;
cin>>op;
if(op=='Q')
{
int l,r,k;
cin>>l>>r>>k;
ops[i]={op,l,r,k,0,0};
}
else
{
int id,y;
cin>>id>>y;
val[++cnt]=y;
ops[i].c=op,ops[i].id=id,ops[i].y=y;
}
}
sort(val+1,val+1+cnt);
cnt=unique(val+1,val+1+cnt)-val-1;
for(int i=1;i<=n;i++) szmotify(i,findid(a[i]),1);
for(int i=1;i<=m;i++)
{
char c=ops[i].c;
if(c=='Q')
{
int l=ops[i].l,r=ops[i].r,k=ops[i].k;
cout<<szquery(l-1,r,k)<<'\n';
}
else
{
int id=ops[i].id,y=ops[i].y;
szmotify(id,findid(a[id]),-1);
swap(a[id],y);
szmotify(id,findid(a[id]),1);
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T=1;
while(T--){solve();}
return 0;
}