bzoj1901zoj2112

来源:互联网 发布:网络财经编辑招聘 编辑:程序博客网 时间:2024/05/21 19:34

bzoj1901听说不用建静态主席树,可以直接当树状数组添加也不会爆内存,然而并没有权限号。由于zoj2112的n有5*1e5所以不能一开始就nlognlogn的空间丢进去,不然会炸,需要建一颗nlogn空间的静态线段树,然后再mlognlogn的跟新,这样就不会爆数组。静态开一个rt1[maxl],动态开一个rt2[maxl]

因为是要动态修改的区间第k大,把主席树当树状数组来看待,要求l到r的第k大就是,求用前r减去前l-1,然后用树状数组的方式,来更新和统计。在统计前i个的左子树的总和的时候,要把动态的树状数组主席树的值加起来,然后再加上静态的主席树的值,才能得到权值为l到r的左子树的总和值。

#include<cstdio>#include<cstring>#include<algorithm>#define maxl 50010#define inf 2000000001using namespace std;int n,m,cnt,tot,sz;int a[maxl],dy[maxl<<1],rt1[maxl],rt2[maxl],inl[maxl],inr[maxl];struct node{int ls,rs,sum;}tree[maxl*50];struct num{int num,ind;bool isa;}aa[maxl<<1];struct que{int l,r,k;bool flag;}q[maxl/5];char ch[2];inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x;}bool cmp(const num &x,const num &y){return x.num<y.num;}void prework(){memset(tree,0,sizeof(tree));memset(rt1,0,sizeof(rt1));memset(rt2,0,sizeof(rt2)); sz=0;n=read();m=read();for(int i=1;i<=n;i++)a[i]=read(),aa[i].num=a[i],aa[i].ind=i,aa[i].isa=true;tot=n;for(int i=1;i<=m;i++){scanf("%s",ch);if(ch[0]=='Q'){q[i].l=read();q[i].r=read();q[i].k=read();q[i].flag=false;}else{q[i].l=read();q[i].k=read();q[i].flag=true;aa[++tot].num=q[i].k;aa[tot].ind=i;aa[tot].isa=false;}}sort(aa+1,aa+1+tot,cmp);cnt=0;aa[0].num=-inf;for(int i=1;i<=tot;i++){if(aa[i].num!=aa[i-1].num)cnt++,dy[cnt]=aa[i].num;if(aa[i].isa)a[aa[i].ind]=cnt;elseq[aa[i].ind].k=cnt;}}void update(int last,int l,int r,int &root,int w,int x){root=++sz;tree[sz]=tree[last];tree[sz].sum+=x;if(l==r)return;int mid=(l+r)>>1;if(w<=mid)update(tree[last].ls,l,mid,tree[sz].ls,w,x);elseupdate(tree[last].rs,mid+1,r,tree[sz].rs,w,x);}int query(int l,int r,int k,int s1,int s2){if(l==r) return l;int i,suml=0,sumr=0;for(int i=1;i<=inl[0];i++) suml+=tree[tree[inl[i]].ls].sum;for(int i=1;i<=inr[0];i++) sumr+=tree[tree[inr[i]].ls].sum;suml+=tree[tree[s1].ls].sum;sumr+=tree[tree[s2].ls].sum;int mid=(l+r)>>1,tmp=sumr-suml;if(tmp>=k){for(int i=1;i<=inl[0];i++) inl[i]=tree[inl[i]].ls;for(int i=1;i<=inr[0];i++) inr[i]=tree[inr[i]].ls;return query(l,mid,k,tree[s1].ls,tree[s2].ls);}else{for(int i=1;i<=inl[0];i++) inl[i]=tree[inl[i]].rs;for(int i=1;i<=inr[0];i++) inr[i]=tree[inr[i]].rs;return query(mid+1,r,k-tmp,tree[s1].rs,tree[s2].rs);}}void mainwork(){for(int i=1;i<=n;i++)update(rt1[i-1],1,cnt,rt1[i],a[i],1);for(int i=1;i<=m;i++)if(!q[i].flag){inl[0]=0;inr[0]=0;for(int j=q[i].l-1;j;j-=j&-j)inl[++inl[0]]=rt2[j];for(int j=q[i].r;j;j-=j&-j)inr[++inr[0]]=rt2[j];printf("%d\n",dy[query(1,cnt,q[i].k,rt1[q[i].l-1],rt1[q[i].r])]);}else{for(int j=q[i].l;j<=n;j+=j&-j)update(rt2[j],1,cnt,rt2[j],a[q[i].l],-1);a[q[i].l]=q[i].k;for(int j=q[i].l;j<=n;j+=j&-j) update(rt2[j],1,cnt,rt2[j],a[q[i].l],1);}}int main(){int t=read();for(int i=1;i<=t;i++){prework();mainwork();}return 0;}


原创粉丝点击