树状数组套主席树什么的真的好迷啊……还是整体二分比较平易近人(大雾)。
我们考虑主席树的修改,如果像以前一样前缀动态开点,那么修改一个点就要把后面的主席树全部重建,时间复杂度 O(m×n×logn) ,和暴力差不多嘛……
然后我们考虑在主席树外面套一个树状数组,这样既不会破坏前缀动态开点的性质,同时把时间复杂度降到了 O(m×log2n) ,岂不是美哉?
那么现在的每一个单独的主席树已经不能表示一个区间了,而是用几棵主席树来表示一个区间了,所以才有了那么麻烦的查询。
至于修改,就对于每一个树状数组的节点像主席树一样修改就好了。
然后这题就被A掉啦。
p.s.这是我第一次看到运行0ms的TLE……
附上AC代码:
#include <cstdio>
#include <cctype>
#include <algorithm>
#define lowbit(x) ((x)&(-x))
using namespace std;
const int N=1e4+10;
struct tree{
int lt,rt,sum;
}t[6000010];
int n,m,a[N],b[N<<1],num,q[N][4],tmp,root[N],size,len1,len2,L[30],R[20];
inline char nc(void){
static char ch[100010],*p1=ch,*p2=ch;
return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &a){
static char c=nc();int f=1;
for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
for (a=0;isdigit(c);a=(a<<3)+(a<<1)+c-'0',c=nc());
return (void)(a*=f);
}
#define mid (l+r>>1)
inline void updata(int pre,int &k,int l,int r,int wz,int w){
t[k=++size]=t[pre],t[k].sum+=w;
if (l==r) return;
if (mid>=wz) updata(t[pre].lt,t[k].lt,l,mid,wz,w);
else updata(t[pre].rt,t[k].rt,mid+1,r,wz,w);
return;
}
inline int query(int l,int r,int w){
if (l==r) return l;
int sum1=0,sum2=0;
for (int i=1; i<=len1; ++i) sum1+=t[t[L[i]].lt].sum;
for (int i=1; i<=len2; ++i) sum2+=t[t[R[i]].lt].sum;
if (sum2-sum1>=w){
for (int i=1; i<=len1; ++i) L[i]=t[L[i]].lt;
for (int i=1; i<=len2; ++i) R[i]=t[R[i]].lt;
query(l,mid,w);
}
else {
for (int i=1; i<=len1; ++i) L[i]=t[L[i]].rt;
for (int i=1; i<=len2; ++i) R[i]=t[R[i]].rt;
query(mid+1,r,w-sum2+sum1);
}
}
int main(void){
read(n),read(m),num=n;
for (int i=1; i<=n; ++i) read(a[i]),b[i]=a[i];
for (int i=1; i<=m; ++i){
char c=nc();while (c!='C'&&c!='Q') c=nc();
read(q[i][1]),read(q[i][2]);
if (c=='Q') read(q[i][3]); else b[++num]=q[i][2];
}
sort(b+1,b+1+num),num=unique(b+1,b+1+num)-b-1;
for (int i=1; i<=n; ++i)
for (int j=i; j<=n; j+=lowbit(j)){
tmp=lower_bound(b+1,b+1+num,a[i])-b;
updata(root[j],root[j],1,num,tmp,1);
}
for (int i=1; i<=m; ++i)
if (q[i][3]){
len1=len2=0;
for (int j=q[i][1]-1; j; j-=lowbit(j)) L[++len1]=root[j];
for (int j=q[i][2]; j; j-=lowbit(j)) R[++len2]=root[j];
printf("%d\n",b[query(1,num,q[i][3])]);
}
else {
tmp=lower_bound(b+1,b+1+num,a[q[i][1]])-b;
for (int j=q[i][1]; j<=n; j+=lowbit(j)) updata(root[j],root[j],1,num,tmp,-1);
a[q[i][1]]=q[i][2],tmp=lower_bound(b+1,b+1+num,q[i][2])-b;
for (int j=q[i][1]; j<=n; j+=lowbit(j)) updata(root[j],root[j],1,num,tmp,1);
}
return 0;
}