这是我第一次写树状数组套可持久化数据结构,写了好长时间……
首先你需要AC POJ2104
然后把一个个递增的版本用树状数组维护就好了
为什么呢?因为你维护的是权值线段树,需要得到的值其实是作差得来的。
那么我们用类似树状数组的作差方法就可以了。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int siz,n,m,a[10005],tab[500005],tb,root[10005],A[10005],B[10005],An,Bn;
struct SegTree{
int nl,nr,sum;
}tree[2000005];
struct Ask{
int opt,l,r,k;
}ask[10005];
int lowbit(int x){return x&(-x);}
int Div(int x){
int l=1,r=tb;
while(l<=r){
int mid=l+r>>1;
if(tab[mid]<x)l=mid+1;
else r=mid-1;
}
return l;
}
void AddTree(int lastrt,int l,int r,int &rt,int pos,int val){
if(rt==0)rt=++siz;
tree[rt].sum=tree[lastrt].sum+val;
tree[rt].nl=tree[lastrt].nl;
tree[rt].nr=tree[lastrt].nr;
if(l==r)return;
int mid=l+r>>1;
if(pos<=mid)AddTree(tree[lastrt].nl,l,mid,tree[rt].nl,pos,val);
else AddTree(tree[lastrt].nr,mid+1,r,tree[rt].nr,pos,val);
}
int Sum(int l,int r,int k){
if(l==r)return l;
int sumL=0,sumR=0,mid=l+r>>1;
for(int i=1;i<=An;i++)sumL+=tree[tree[A[i]].nl].sum;
for(int i=1;i<=Bn;i++)sumR+=tree[tree[B[i]].nl].sum;
if(sumR-sumL>=k){
for(int i=1;i<=An;i++)A[i]=tree[A[i]].nl;
for(int i=1;i<=Bn;i++)B[i]=tree[B[i]].nl;
return Sum(l,mid,k);
}
else {
for(int i=1;i<=An;i++)A[i]=tree[A[i]].nr;
for(int i=1;i<=Bn;i++)B[i]=tree[B[i]].nr;
return Sum(mid+1,r,k-sumR+sumL);
}
}
int main(){
freopen("1901.in","r",stdin);
freopen("1901.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
tab[++tb]=a[i];
}
for(int i=1;i<=m;i++){
char s[5];
scanf("%s",s);
if(s[0]=='C'){
scanf("%d %d",&ask[i].l,&ask[i].k);
ask[i].opt=1;
tab[++tb]=ask[i].k;
}
if(s[0]=='Q'){
scanf("%d %d %d",&ask[i].l,&ask[i].r,&ask[i].k);
ask[i].opt=2;
ask[i].l--;
}
}
sort(tab+1,tab+tb+1);
tb=unique(tab+1,tab+tb+1)-tab-1;
for(int i=1;i<=n;i++){
int x=Div(a[i]);
for(int j=i;j<=n;j+=lowbit(j))AddTree(root[j],1,tb,root[j],x,1);
}
for(int i=1;i<=m;i++){
if(ask[i].opt==1){
int x=Div(a[ask[i].l]);
for(int j=ask[i].l;j<=n;j+=lowbit(j))AddTree(root[j],1,tb,root[j],x,-1);
a[ask[i].l]=ask[i].k;
x=Div(ask[i].k);
for(int j=ask[i].l;j<=n;j+=lowbit(j))AddTree(root[j],1,tb,root[j],x,1);
}
else {
An=Bn=0;
for(int j=ask[i].l;j;j-=lowbit(j))A[++An]=root[j];
for(int j=ask[i].r;j;j-=lowbit(j))B[++Bn]=root[j];
printf("%d\n",tab[Sum(1,tb,ask[i].k)]);
}
}
return 0;
}