【BZOJ】【1901】【Zju2112】 Dynamic Rankings
2015-01-02 21:40
330 查看
再填个坑。
也就是说,每次修改,一块改logn棵线段树;每次查询也是在logn棵线段树上一起往下找!
P.S.本题需将所有数(包括修改后的数)进行离散化
View Code
动态维护区间第K大(带单点修改)
首先裸的区间第K大我们是用的【前缀和】思想,实现O(n)预处理,O(1)找树查询,那么如果是动态的呢?我们可以利用树状数组(BIT)的思想,进行O(logn)的修改,O(logn)的查询(当然由于是在线段树上做,都各需要再乘logn的复杂度)也就是说,每次修改,一块改logn棵线段树;每次查询也是在logn棵线段树上一起往下找!
P.S.本题需将所有数(包括修改后的数)进行离散化
//BZOJ 1901 #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define rep(i,n) for(int i=0;i<n;++i) #define F(i,j,n) for(int i=j;i<=n;++i) #define D(i,j,n) for(int i=j;i>=n;--i) #define lowbit(x) ((x)&(-(x))) using namespace std; const int N=110086; struct Tree{ int cnt,l,r; }t[N*30]; int n,m,num=0,root ,a[N>>1],b ,dat[N>>1][4],size=0,cnt=0; int lc,rc,ln ,rn ; #define mid (l+r>>1) void build(int &o,int l,int r){ o=++cnt; t[o].cnt=0; if (l==r) return; build(t[o].l,l,mid); build(t[o].r,mid+1,r); } void updata(int &o,int l,int r,int pos,int val){ t[++cnt]=t[o],o=cnt,t[o].cnt+=val; if (l==r) return; if (pos <= mid) updata(t[o].l,l,mid,pos,val); else updata(t[o].r,mid+1,r,pos,val); } void modify(int x,int pos,int val){ for(x;x<=n;x+=lowbit(x) )//一次改logn棵树 updata(root[x],1,num,pos,val); } int query(int i,int j,int rank){ int l=1,r=num; int tl=0,tr=0; while(l!=r){ tl=tr=0; F(i,1,lc) tl+=t[t[ln[i]].l].cnt;//将logn棵树的和加出来 F(i,1,rc) tr+=t[t[rn[i]].l].cnt; if (tr-tl>=rank){ F(i,1,lc) ln[i]=t[ln[i]].l;//向左找 F(i,1,rc) rn[i]=t[rn[i]].l; r=mid; } else{ F(i,1,lc) ln[i]=t[ln[i]].r;//向右找 F(i,1,rc) rn[i]=t[rn[i]].r; l=mid+1; rank-=tr-tl; } } return l; } #undef mid int getans(int l,int r,int k){ rc=lc=0; for(r;r;r-=lowbit(r)) rn[++rc]=root[r]; for(l;l;l-=lowbit(l)) ln[++lc]=root[l]; return query(1,num,k); } void solve(){ sort(b+1,b+size+1); num=unique(b+1,b+size+1)-b-1;//这个神奇的用法……是什么意思? F(i,1,n) a[i]=lower_bound(b+1,b+num+1,a[i])-b; build(root[0],1,num); F(i,1,n) modify(i,a[i],1); F(i,1,m){ if(dat[i][0]==0) printf("%d\n",b[ getans(dat[i][1]-1,dat[i][2],dat[i][3]) ]); else{ int pos=lower_bound(b+1,b+num+1,dat[i][2])-b; modify(dat[i][1],a[dat[i][1]],-1); a[dat[i][1]]=pos; modify(dat[i][1],a[dat[i][1]],1); } } } int main(){ #ifndef ONLINE_JUDGE freopen("file.in","r",stdin); #endif int T=1; // scanf("%d",&T); while(T--){ size=cnt=num=0; memset(b,0,sizeof b); memset(t,0,sizeof t); memset(dat,0,sizeof dat); scanf("%d%d",&n,&m); F(i,1,n){ scanf("%d",&a[i]); b[++size]=a[i]; } char cmd[3]; F(i,1,m){ scanf("%s",cmd); if (cmd[0]=='C'){ dat[i][0]=1; scanf("%d%d",&dat[i][1],&dat[i][2]); b[++size]=dat[i][2]; } else{ dat[i][0]=0; scanf("%d%d%d",&dat[i][1],&dat[i][2],&dat[i][3]); } } solve(); } return 0; } /************************************************** 利用BIT的思想,实现前缀-差分的logn的转化 裸的可持久化线段树是每棵树维护一个区间[1,i](前缀和) 查询O(1),而修改就需要 O(n)了 而动态进行修改&查询-->BIT里套一个可持久化线段树 BIT的每个节点表示原数组的一个区间 然后用可持久化线段树来维护这个区间 查询的时候log(n)棵线段树一起查 **************************************************/
View Code
相关文章推荐
- [BZOJ]1901: Zju2112 Dynamic Rankings 主席树
- bzoj 1901: Zju2112 Dynamic Rankings(离线树状数组+主席树)
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
- 【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题
- BZOJ 1901 Zju2112 Dynamic Rankings ——整体二分
- [BZOJ1901][ZJU2112]Dynamic Rankings
- [Bzoj1901]Zju2112 Dynamic Rankings
- [Bzoj1901]Zju2112 Dynamic Rankings
- bzoj 1901: Zju2112 Dynamic Rankings(树套树)
- bzoj 1901: Zju2112 Dynamic Rankings
- 【BZOJ 1901】 Zju2112 Dynamic Rankings|树状数组套主席树
- BZOJ 1901: Zju2112 Dynamic Rankings( BIT 套 BST )
- 【bzoj1901】Zju2112 Dynamic Rankings 线段树套平衡树
- BZOJ 1901 Zju2112 Dynamic Rankings
- bzoj 1901: Zju2112 Dynamic Rankings 树状数组套线段树 cdq分治
- 【bzoj1901】Zju2112 Dynamic Rankings
- 主席树初探--BZOJ1901: Zju2112 Dynamic Rankings
- [bzoj1901]: Zju2112 Dynamic Rankings
- 【题解】BZOJ 1901: Zju2112 Dynamic Rankings
- bzoj 1901: Zju2112 Dynamic Rankings(树套树)