人生第二发树套树。
话说原来树套树跑得比整体二分快啊,真不科学。
整体二分260MS,树套树130MS,快了一倍。
这题嘛就树状数组套主席树。
一开始建一颗空的主席树,以后的树都在这基础上搞。
于是有两套主席树。
第一套是原数组的,依次在前一颗树上建。
第二套是修改出来的主席树,套上树状数组,树状数组修改的时候在之前的树上建。
然后询问的时候要将两套主席树的影响都加上,于是就差不多了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define lb(x) (x&-x)
using namespace std;
const int N=60000+10;
const int M=2500000+10;
int a[N],n,nq,m;
int S[N],T[N],lc[M],rc[M],w[M],cnt;
int hash[N];
void init(){
sort(hash+1,hash+1+m);
m=unique(hash+1,hash+1+m)-hash-1;
}
int find(int x){
return lower_bound(hash+1,hash+m+1,x)-hash;
}
int build(int l,int r){
int rt=++cnt;
w[rt]=0;
if(l!=r){
int mid=l+r>>1;
lc[rt]=build(l,mid);
rc[rt]=build(mid+1,r);
}
return rt;
}
int insert(int rt,int pos,int val){
int nrt=++cnt,tmp=nrt;
int l=1,r=m;
w[nrt]=w[rt]+val;
while(l<r){
int mid=l+r>>1;
if(pos<=mid){
lc[nrt]=++cnt;rc[nrt]=rc[rt];
nrt=lc[nrt];rt=lc[rt];
r=mid;
}else{
rc[nrt]=++cnt;lc[nrt]=lc[rt];
nrt=rc[nrt];rt=rc[rt];
l=mid+1;
}
w[nrt]=w[rt]+val;
}
return tmp;
}
int use[N];
void add(int x,int p,int d){
for(;x<=n;x+=lb(x))S[x]=insert(S[x],p,d);
}
int sum(int x){
int ret=0;
for(;x>0;x-=lb(x))ret+=w[lc[use[x]]];
return ret;
}
int query(int a,int b,int k){
int x=T[a-1],y=T[b];
int l=1,r=m;
for(int i=a-1;i;i-=lb(i))use[i]=S[i];
for(int i=b;i;i-=lb(i))use[i]=S[i];
while(l<r){
int mid=l+r>>1;
int tmp=sum(b)-sum(a-1)+w[lc[y]]-w[lc[x]];
if(tmp>=k){
r=mid;
for(int i=a-1;i;i-=lb(i))use[i]=lc[use[i]];
for(int i=b;i;i-=lb(i))use[i]=lc[use[i]];
x=lc[x];y=lc[y];
}else{
l=mid+1;
k-=tmp;
for(int i=a-1;i;i-=lb(i))use[i]=rc[use[i]];
for(int i=b;i;i-=lb(i))use[i]=rc[use[i]];
x=rc[x];y=rc[y];
}
}
return l;
}
struct Query{
int l,r,k,kind;
}q[10005];
template<class T>void read(T &x){
static char c;
static bool f;
for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1;
for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
if(f)x=-x;
}
int main(){
int kase;read(kase);
while(kase--){
read(n);read(nq);
cnt=0;m=0;
for(int i=1;i<=n;i++){
read(a[i]);hash[++m]=a[i];
}
char opt[5];
for(int i=1;i<=nq;i++){
scanf("%s",opt);
if(opt[0]=='Q'){
read(q[i].l);read(q[i].r);read(q[i].k);
q[i].kind=1;
}else{
read(q[i].l);read(q[i].r);
q[i].kind=0;
hash[++m]=q[i].r;
}
}
init();
T[0]=build(1,m);
for(int i=1;i<=n;i++)
T[i]=insert(T[i-1],find(a[i]),1);
for(int i=1;i<=n;i++)S[i]=T[0];
for(int i=1;i<=nq;i++){
if(q[i].kind)printf("%d\n",hash[query(q[i].l,q[i].r,q[i].k)]);
else{
add(q[i].l,find(a[q[i].l]),-1);
add(q[i].l,find(q[i].r),1);
a[q[i].l]=q[i].r;
}
}
}
return 0;
}