可持久化数组:
struct PersistentArray
{
const static int __=1e6+5;
#define ls(x) t[x].lson
#define rs(x) t[x].rson
struct node
{
int val,lson,rson;
void clear()
{
val=lson=rson=0;
}
}t[__*20];
int *a,n,idx;
int root[__*20],rt;
PersistentArray() {clear();}
void build(int _a[],int _n)
{
a=_a,n=_n;
root[0]=++idx;
t[idx].clear();
build(root[0],1,n);
}
void build(int x,int tl,int tr)
{
if(tl==tr)
{
t[x].val=a[tl];
return;
}
int tm=(tl+tr)>>1;
t[ls(x)=++idx].clear();
build(ls(x),tl,tm);
t[rs(x)=++idx].clear();
build(rs(x),tm+1,tr);
}
//基于版本y, x位置的值改为v, 返回新链的根
int set(int y,int x,int v)
{
y=root[y];
t[root[++rt]=++idx].clear();
_set(y,root[rt],x,v);
return root[rt];
}
void _set(int pn,int nn,int pos,int val)
{
int tl=1,tr=n;
while(tl!=tr)
{
int tm=(tl+tr)>>1;
if(pos<=tm)
{
rs(nn)=rs(pn),ls(nn)=++idx;
pn=ls(pn),nn=idx,tr=tm;
}
else
{
ls(nn)=ls(pn),rs(nn)=++idx;
pn=rs(pn),nn=idx,tl=tm+1;
}
}
t[idx].val=val;
}
//版本y中位置pos的元素
int get(int y,int pos)
{
root[++rt]=root[y];
int tl=1,tr=n,x=root[y];
while(tl!=tr)
{
int tm=(tl+tr)>>1;
if(pos<=tm)
x=ls(x),tr=tm;
else
x=rs(x),tl=tm+1;
}
return t[x].val;
}
void clear() {idx=rt=0;}
}pa;
静态主席树:
struct Discretization
{
const static int __=1e5+5;
ll a[__],b[__];int idx;
Discretization() {clear();}
ll operator[](int x){return b[x];}
void push_back(ll x){a[++idx]=x;}
void build()
{
sort(a+1,a+1+idx);
idx=unique(a+1,a+1+idx)-a-1;
}
int get(ll x)
{
int y=lower_bound(a+1,a+1+idx,x)-a;
b[y]=x;
return y;
}
void clear() {idx=0;}
}D;
//权值主席树
struct PersistentSegmentTree
{
#define ls(x) t[x].lson
#define rs(x) t[x].rson
const static int __=1e5+5;
const static int nlogn=__*((int)log2(__)+2);
struct node
{
int lson,rson,val;
void clear()
{
val=lson=rson=0;
}
}t[nlogn];
int n,idx,pos,val;
int root[__],rt;
PersistentSegmentTree() {t[0].clear();clear();}
void build(int _n)
{
clear();n=_n;D.clear();
for(int i=1;i<=n;++i)
D.pb(a[i]);
D.build();
for(int i=1;i<=n;++i)
add(D.get(a[i]),1);
}
void pushup(int x)
{
t[x].val=t[ls(x)].val+t[rs(x)].val;
}
//位置x的值+v
void add(int x,int v)
{
pos=x,val=v;
root[++rt]=++idx;
t[idx].clear();
_add(root[rt-1],root[rt],1,n);
}
//pn:前一个节点 nn:当前节点
void _add(int pn,int nn,int tl,int tr)
{
int tm=(tl+tr)>>1;
if(tl==pos && pos==tr)
{
t[nn].val=t[pn].val+val;
return;
}
if(pos<=tm)
{
rs(nn)=rs(pn),ls(nn)=++idx;
t[idx].clear();
_add(ls(pn),idx,tl,tm);
}
else
{
ls(nn)=ls(pn),rs(nn)=++idx;
t[idx].clear();
_add(rs(pn),idx,tm+1,tr);
}
pushup(nn);
}
//区间[l,r]第k大的值
ll kth(int l,int r,int k)
{
return D[_kth(root[l-1],root[r],1,n,k)];
}
int _kth(int ln,int rn,int tl,int tr,int k)
{
if(tl==tr)return tl;
int lv=t[ls(rn)].val-t[ls(ln)].val;
int tm=(tl+tr)>>1;
if(k<=lv)
return _kth(ls(ln),ls(rn),tl,tm,k);
return _kth(rs(ln),rs(rn),tm+1,tr,k-lv);
}
void clear() {idx=rt=0;}
}pst;
主席树(单点修改):
int lowbit(int x)
{
return x&(-x);
}
struct node
{
int lson,rson,val;
node():val(0),lson(0),rson(0) {}
} tree[1400000];
int a[50005],lisan[60005],que[10005][4];
int ys[60005],root[50005],l_node[30],r_node[30];
int idx;
void build(int pre,int id,int tl,int tr,int wz,int val)
{
tree[id].val=tree[pre].val+val;
if(tl==wz && wz==tr)
return;
int tm=(tl+tr)>>1;
if(wz<=tm)
{
tree[id].rson=tree[pre].rson;
tree[id].lson=++idx;
build(tree[pre].lson,idx,tl,tm,wz,val);
}
else
{
tree[id].lson=tree[pre].lson;
tree[id].rson=++idx;
build(tree[pre].rson,idx,tm+1,tr,wz,val);
}
}
int query(int l_num,int r_num,int tl,int tr,int l_now,int r_now,int k)
{
if(tl==tr)return tl;
int sum=tree[tree[r_now].lson].val-tree[tree[l_now].lson].val;
for(int i=1; i<=l_num; i++)
sum-=tree[tree[l_node[i]].lson].val;
for(int i=1; i<=r_num; i++)
sum+=tree[tree[r_node[i]].lson].val;
int tm=(tl+tr)>>1;
if(k<=sum)
{
for(int i=1; i<=l_num; i++)
l_node[i]=tree[l_node[i]].lson;
for(int i=1; i<=r_num; i++)
r_node[i]=tree[r_node[i]].lson;
return query(l_num,r_num,tl,tm,tree[l_now].lson,tree[r_now].lson,k);
}
else
{
for(int i=1; i<=l_num; i++)
l_node[i]=tree[l_node[i]].rson;
for(int i=1; i<=r_num; i++)
r_node[i]=tree[r_node[i]].rson;
return query(l_num,r_num,tm+1,tr,tree[l_now].rson,tree[r_now].rson,k-sum);
}
}
void update(int num,int tl,int tr,int wz,int val)
{
if(tl==wz && wz==tr)
{
for(int i=1; i<=num; i++)
tree[l_node[i]].val+=val;
return;
}
int tm=(tl+tr)>>1;
if(wz<=tm)
{
for(int i=1; i<=num; i++)
{
tree[l_node[i]].val+=val;
if(!tree[l_node[i]].lson)
tree[l_node[i]].lson=++idx;
l_node[i]=tree[l_node[i]].lson;
}
update(num,tl,tm,wz,val);
}
else
{
for(int i=1; i<=num; i++)
{
tree[l_node[i]].val+=val;
if(!tree[l_node[i]].rson)
tree[l_node[i]].rson=++idx;
l_node[i]=tree[l_node[i]].rson;
}
update(num,tm+1,tr,wz,val);
}
}
void init(void)
{
memset(a,0,sizeof(a));
memset(tree,0,sizeof(tree));
memset(que,0,sizeof(que));
memset(ys,0,sizeof(ys));
memset(root,0,sizeof(root));
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
int n,q,k=0;
scanf("%d%d",&n,&q);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
lisan[k++]=a[i];
}
for(int i=1; i<=q; i++)
{
char op[2];
scanf("%s",op);
if(op[0]=='Q')
{
que[i][0]=0;
for(int j=1; j<=3; j++)
scanf("%d",&que[i][j]);
}
if(op[0]=='C')
{
que[i][0]=1;
for(int j=1; j<=2; j++)
scanf("%d",&que[i][j]);
lisan[k++]=que[i][2];
}
}
idx=n;
sort(lisan,lisan+k);
int len=unique(lisan,lisan+k)-lisan;
for(int i=1; i<=n; i++)
{
int x=lower_bound(lisan,lisan+len,a[i])-lisan+1;
ys[x]=a[i];
build(i-1,i,1,len,x,1);
}
for(int i=1; i<=q; i++)
{
if(que[i][0]==0)
{
int l_num=0,r_num=0;
for(int j=que[i][1]-1; j; j-=lowbit(j))
{
l_node[++l_num]=root[j];
}
for(int j=que[i][2]; j; j-=lowbit(j))
{
r_node[++r_num]=root[j];
}
int res=query(l_num,r_num,1,len,que[i][1]-1,que[i][2],que[i][3]);
printf("%d\n",ys[res]);
}
if(que[i][0]==1)
{
int x=lower_bound(lisan,lisan+len,a[que[i][1]])-lisan+1;
int num=0;
for(int j=que[i][1]; j<=n; j+=lowbit(j))
{
if(!root[j])root[j]=++idx;
l_node[++num]=root[j];
}
update(num,1,len,x,-1);
a[que[i][1]]=que[i][2];
num=0;
for(int j=que[i][1]; j<=n; j+=lowbit(j))
{
l_node[++num]=root[j];
}
x=lower_bound(lisan,lisan+len,que[i][2])-lisan+1;
ys[x]=que[i][2];
update(num,1,len,x,1);
}
}
}
return 0;
}
主席树(单点修改):
ll nixudui=0;
void guibing(int st,int mid,int ed,int a[],int t[])
{
int x=st,y=mid+1,k=st,num=mid-st+1;
while(x<=mid&&y<=ed)
if(a[x]<=a[y])
t[k++]=a[x++],num--;
else
t[k++]=a[y++],nixudui+=num;
while(x<=mid)t[k++]=a[x++];
while(y<=ed)t[k++]=a[y++];
for(int i=st; i<=ed; i++)
a[i]=t[i];
}
void merge_sort(int st,int ed,int a[],int t[])
{
int mid=(st+ed)>>1;
if(st!=mid)merge_sort(st,mid,a,t);
if(mid+1!=ed)merge_sort(mid+1,ed,a,t);
guibing(st,mid,ed,a,t);
}
int lowbit(int x)
{
return x&(-x);
}
struct node
{
int lson,rson,val;
node():val(0),lson(0),rson(0) {}
} tree[7000000];
int a[100005],root[100005],wz[100005],t[100005];
int l_node[55],r_node[55];
int idx;
void build(int pre,int id,int tl,int tr,int wz,int val)
{
tree[id].val=tree[pre].val+val;
if(tl==wz && wz==tr)
return;
int tm=(tl+tr)>>1;
if(wz<=tm)
{
tree[id].rson=tree[pre].rson;
tree[id].lson=++idx;
build(tree[pre].lson,idx,tl,tm,wz,val);
}
else
{
tree[id].lson=tree[pre].lson;
tree[id].rson=++idx;
build(tree[pre].rson,idx,tm+1,tr,wz,val);
}
}
int query_max(int l_num,int r_num,int tl,int tr,int id,int x)
{
if(tl==tr)return 0;
int tm=(tl+tr)>>1,sum=0;
if(x<=tm)
{
sum+=tree[tree[id].rson].val;
for(int i=1; i<=l_num; i++)
{
sum-=tree[tree[l_node[i]].rson].val;
l_node[i]=tree[l_node[i]].lson;
}
for(int i=1; i<=r_num; i++)
{
sum+=tree[tree[r_node[i]].rson].val;
r_node[i]=tree[r_node[i]].lson;
}
return sum+query_max(l_num,r_num,tl,tm,tree[id].lson,x);
}
else
{
for(int i=1; i<=l_num; i++)
l_node[i]=tree[l_node[i]].rson;
for(int i=1; i<=r_num; i++)
r_node[i]=tree[r_node[i]].rson;
return query_max(l_num,r_num,tm+1,tr,tree[id].rson,x);
}
}
int query_min(int l_num,int r_num,int tl,int tr,int pre,int id,int x)
{
if(tl==tr)return 0;
int tm=(tl+tr)>>1,sum=0;
if(x<=tm)
{
for(int i=1; i<=l_num; i++)
l_node[i]=tree[l_node[i]].lson;
for(int i=1; i<=r_num; i++)
r_node[i]=tree[r_node[i]].lson;
return query_min(l_num,r_num,tl,tm,tree[pre].lson,tree[id].lson,x);
}
else
{
sum+=tree[tree[id].lson].val-tree[tree[pre].lson].val;
for(int i=1; i<=l_num; i++)
{
sum-=tree[tree[l_node[i]].lson].val;
l_node[i]=tree[l_node[i]].rson;
}
for(int i=1; i<=r_num; i++)
{
sum+=tree[tree[r_node[i]].lson].val;
r_node[i]=tree[r_node[i]].rson;
}
return sum+query_min(l_num,r_num,tm+1,tr,tree[pre].rson,tree[id].rson,x);
}
}
void update(int num,int tl,int tr,int wz,int val)
{
if(tl==wz && wz==tr)
{
for(int i=1; i<=num; i++)
tree[l_node[i]].val+=val;
return;
}
int tm=(tl+tr)>>1;
if(wz<=tm)
{
for(int i=1; i<=num; i++)
{
tree[l_node[i]].val+=val;
if(!tree[l_node[i]].lson)
tree[l_node[i]].lson=++idx;
l_node[i]=tree[l_node[i]].lson;
}
update(num,tl,tm,wz,val);
}
else
{
for(int i=1; i<=num; i++)
{
tree[l_node[i]].val+=val;
if(!tree[l_node[i]].rson)
tree[l_node[i]].rson=++idx;
l_node[i]=tree[l_node[i]].rson;
}
update(num,tm+1,tr,wz,val);
}
}
int main()
{
int n,q,x;
scanf("%d%d",&n,&q);
idx=n;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
wz[a[i]]=i;
build(i-1,i,1,n,a[i],1);
}
merge_sort(1,n,a,t);
printf("%lld\n",nixudui);
int l_num=0,r_num=0,num=0;
while(q--)
{
scanf("%d",&x);
l_num=0,r_num=0;
for(int j=wz[x]; j; j-=lowbit(j))
r_node[++r_num]=root[j];
int left_max=query_max(l_num,r_num,1,n,wz[x],x);
l_num=0,r_num=0;
for(int j=wz[x]-1; j; j-=lowbit(j))
l_node[++l_num]=root[j];
for(int j=n; j; j-=lowbit(j))
r_node[++r_num]=root[j];
int right_min=query_min(l_num,r_num,1,n,wz[x]-1,n,x);
nixudui-=left_max+right_min;
if(q)printf("%lld\n",nixudui);
num=0;
for(int j=wz[x]; j<=n; j+=lowbit(j))
{
if(!root[j])root[j]=++idx;
l_node[++num]=root[j];
}
update(num,1,n,x,-1);
}
return 0;
}