这时容易发现,只要把树状数组上的每一个节点换成一颗主席树就行了,
单点修改,直接按照树状数组的修改就行了。
如果不理解的话,就想象一下树状数组的每一个节点挂了一颗主席树。
时间复杂度
主席树查询复杂度为(nlogn),树状数组时间复杂度为(logn),所以时间复杂度为(n{logn}^2)。
空间复杂度
主席树空间复杂度为(nlogn),每个节点最多存入(logn)个树状数组(因为每次加lowbit(i)),
由于我们是在线开点,所以空间复杂度为(n{logn}^2)。
代码如下:
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100010],hash[101000],tot,root[201000],cnt,n,m,tt,qll[200100],qrr[20000];
int q1,q2,id[201000],b[201000];
struct TREE
{
int ln,rn,zhi;
}t[10010000];
struct NODE
{
int l,r,k,flag;
}q[100100];
int lowbit(int x) {return (x)&(-x);}
void gai(int &node,int l,int r,int hs,int v)
{
if(!node) node=++tot;
t[node].zhi+=v;
if(l==r) return;
int mid=(l+r)/2;
if(hs<=mid) gai(t[node].ln,l,mid,hs,v);
else gai(t[node].rn,mid+1,r,hs,v);
}
void add(int p,int v)
{
hash[p]=lower_bound(a+1,a+1+tt,hash[p])-a;
//cout<<hash[p]<<endl;
for(int i=p;i<=n;i+=lowbit(i)) gai(root[i],1,tt,hash[p],v);
}
char s[2];
int SUM()
{
int ans1=0,ans2=0;
for(int i=1;i<=q1;i++) ans1+=t[t[qrr[i]].ln].zhi;
for(int i=1;i<=q2;i++) ans2+=t[t[qll[i]].ln].zhi;
return ans1-ans2;
}
int cha(int qr,int ql,int l,int r,int k)
{
q1=0,q2=0;
for(int i=qr;i>=1;i-=lowbit(i)) qrr[++q1]=root[i];
for(int i=ql;i>=1;i-=lowbit(i)) qll[++q2]=root[i];
while(l<r)
{
int lsiz=SUM(),mid=(l+r)/2;
if(k<=lsiz)
{
for(int i=1;i<=q1;i++) qrr[i]=t[qrr[i]].ln;
for(int i=1;i<=q2;i++) qll[i]=t[qll[i]].ln;
r=mid;
}
else
{
for(int i=1;i<=q1;i++) qrr[i]=t[qrr[i]].rn;
for(int i=1;i<=q2;i++) qll[i]=t[qll[i]].rn;
l=mid+1;k-=lsiz;
}
}
return l;
}
int main()
{
int x,y,z;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);b[i]=a[i];
hash[++cnt]=a[i];
}
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='Q')
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k),q[i].flag=1;
else
{
scanf("%d%d",&q[i].l,&q[i].r);
a[++cnt]=q[i].r;hash[cnt]=a[cnt];
}
}
sort(a+1,a+1+cnt);
tt=unique(a+1,a+1+cnt)-a-1;
for(int i=1;i<=n;i++)
add(i,1);
for(int i=1;i<=m;i++)
{
if(q[i].flag==1)
printf("%d
",a[cha(q[i].r,q[i].l-1,1,tt,q[i].k)]);
else
{
hash[q[i].l]=b[q[i].l];
add(q[i].l,-1);
hash[q[i].l]=q[i].r;
b[q[i].l]=q[i].r;
add(q[i].l,1);
}
}
}