带修改的主席树
Posted Candy?
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带修改的主席树相关的知识,希望对你有一定的参考价值。
普通主席树认为是前缀套线段树,那么这就是树状数组套线段树
前缀区间由原来的一个前缀一个线段树变成BIT组成的几棵线段树一起
每个线段树维护的还是离散排序后的数列
每个节点也相当于一个主席树,我觉得更像是线段树,但是修改的时候用到了主席树的方法,就是在原来的基础上修改(只不过这些原来的都不保存)
add操作要修改一些主席树
sum操作要加一些主席树的区间和
外层的BIT是为了处理询问区间,内层是为了找k值
kth时候要把用到的主席树提出了,每个都往左往右
代码(未提交过)
// // main.cpp // zoj2112 // // Created by Candy on 2016/12/11. // Copyright © 2016年 Candy. All rights reserved. // #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N=6e4+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();} return x*f; } int n,Q,m,a[N],mp[N],i,j,k; char s[2]; struct question{ char s[2]; int i,j,k,x,d; }q[N]; inline int Bin(int v){ int l=1,r=m; while(l<=r){ int mid=(l+r)>>1; if(mp[mid]==v) return mid; if(mp[mid]>v) r=mid-1; else l=mid+1; } return -1; } inline int lowbit(int x){return x&-x;} int c[N]; struct node{ int lc,rc,w; }t[N*20]; int cnt=0,root[N]; void ins(int &x,int l,int r,int num,int v){//1 -1 t[++cnt]=t[x];x=cnt; t[x].w+=v; if(l==r) return; int mid=(l+r)>>1; if(num<=mid) ins(t[x].lc,l,mid,num,v); else ins(t[x].rc,mid+1,r,num,v); } void add(int p,int v){ int _=Bin(a[p]); for(int i=p;i<=n;i+=lowbit(i)) ins(root[i],1,m,_,v);//1...m } int cur[N],ql,qr; int sum(int p){ int ret=0; for(int i=p;i;i-=lowbit(i)) ret+=t[t[cur[i]].lc].w;//lc return ret; } int query(int l,int r,int k){//printf("query %d %d %d\n",l,r,k); if(l==r) return l; int ls=sum(qr)-sum(ql-1),mid=(l+r)>>1; if(k<=ls){ for(int i=ql-1;i;i-=lowbit(i)) cur[i]=t[cur[i]].lc; for(int i=qr;i;i-=lowbit(i)) cur[i]=t[cur[i]].lc; return query(l,mid,k); }else{ for(int i=ql-1;i;i-=lowbit(i)) cur[i]=t[cur[i]].rc; for(int i=qr;i;i-=lowbit(i)) cur[i]=t[cur[i]].rc; return query(mid+1,r,k-ls); } } void solve(){ cnt=0; memset(root,0,sizeof(root)); for(int i=1;i<=n;i++) add(i,1); for(int i=1;i<=Q;i++){ if(q[i].s[0]==‘Q‘){ ql=q[i].i,qr=q[i].j; for(int i=ql-1;i;i-=lowbit(i)) cur[i]=root[i]; for(int i=qr;i;i-=lowbit(i)) cur[i]=root[i]; printf("%d\n",mp[query(1,m,q[i].k)]); }else{ add(q[i].x,-1); a[q[i].x]=q[i].d; add(q[i].x,1); } } } int main(int argc, const char * argv[]) { int T=read(); while(T--){ //init m=0;memset(mp,0,sizeof(mp)); n=read();Q=read(); for(int i=1;i<=n;i++) a[i]=mp[++m]=read(); for(int i=1;i<=Q;i++){ scanf("%s",q[i].s); if(q[i].s[0]==‘Q‘) q[i].i=read(),q[i].j=read(),q[i].k=read(); else q[i].x=read(),q[i].d=mp[++m]=read(); } sort(mp+1,mp+1+m); int p=0;mp[++p]=mp[1]; for(int i=2;i<=m;i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i]; m=p; //for(int i=1;i<=m;i++) printf("mp %d\n",mp[i]); solve(); } return 0; }
以上是关于带修改的主席树的主要内容,如果未能解决你的问题,请参考以下文章
Luogu Dynamic Ranking (带修改的主席树)
zoj 2112 Dynamic Rankings 带修改区间第K大 动态主席树