zoj-2112(主席树动态求区间第k小数)
来源:互联网 发布:vb.net加载dll 编辑:程序博客网 时间:2024/05/01 12:35
总算是把动态求区间第k个数的算法看明白了。
在主席树的基础上,如果有修改操作,则要通过套树状数组来实现任意区间求第k小的问题。
刚开始看不明白什么意思,现在有一点理解。树状数组的每个元素是一个线段树,来维护修改后的前后缀和,树状数组能在log时间内更整个数组,现在用相同的方式更新整个线段树数组,每次更新一个点时,要更新这个点代表的整个线段树。同样的,求和时用一个use数组记录所要更新的点的下标,每次求不同线段树的同一位置的和。
静态初值不要用来初始化树状数组。
考虑到前缀和,我们通过树状数组来优化,即树状数组套主席树,每个节点都对应一棵主席树,那么修改操作就只要修改logn棵树,
O(nlognlogn+Mlognlogn)时间是可以的,但是直接建树要nlogn*logn(10^7)会MLE。
我们发现对于静态的建树我们只要nlogn个节点就可以了,而且对于修改操作,只是修改M次,每次改变俩个值(减去原先的,加上现
在的)也就是说如果把所有初值都插入到树状数组里是不值得的,所以我们分两部分来做,所有初值按照静态来建,内存O(nlogn),
而修改部分保存在树状数组中,每次修改logn棵树,每次插入增加logn个节点O(M*logn*logn+nlogn)。
//#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<stdio.h>#include<math.h>#include <string>#include<string.h>#include<map>#include<queue>#include<set>#include<utility>#include<vector>#include<algorithm>#include<stdlib.h>using namespace std;#define eps 1e-8#define pii pair<int,int>#define inf 0x3f3f3f3f#define rd(x) scanf("%d",&x)#define rd2(x,y) scanf("%d%d",&x,&y)#define ll long long int#define mod 1000000007#define maxn 60005#define maxm 2500005int m,n,nn,tot;int a[maxn],f[maxn],T[maxn],S[maxn];int sum[maxm],l[maxm],r[maxm];int use[maxn];int h(int x){//该值在离散化后线段树的位置 return lower_bound(f+1,f+1+nn,x)-f;}void update(int pr,int lx,int rx,int v,int k){//插入,即新建第i个线段树 l[++tot]=l[pr];r[tot]=r[pr];sum[tot]=sum[pr]+k; if(lx==rx) return; int mid=(lx+rx)>>1; if(v<=mid) { l[tot]=tot+1; update(l[pr],lx,mid,v,k); } else { r[tot]=tot+1; update(r[pr],mid+1,rx,v,k); }}void build(int rt,int lx,int rx){//初始化空树 sum[rt]=0; if(lx==rx) return; l[rt]=++tot; int mid=(lx+rx)>>1; build(tot,lx,mid); r[rt]=++tot; build(tot,mid+1,rx);}int lowbit(int x){return x&(-x);}int Sum(int x){ int res=0; for(int i=x;i;i-=lowbit(i)) res+=sum[l[use[i]]]; return res;}void add(int x,int v,int k) { int tt; for(int i=x;i<=n;i+=lowbit(i)){ tt=S[i]; S[i]=tot+1; update(tt,1,nn,v,k); } }int query(int L,int R,int k){ for(int i=L-1;i;i-=lowbit(i)) use[i]=S[i];//use记录要操作的线段树下标 for(int i=R;i;i-=lowbit(i)) use[i]=S[i]; int lx=1,rx=nn; int lt=T[L-1],rt=T[R]; while(lx<rx){ int mid=(lx+rx)>>1; int tmp=Sum(R)-Sum(L-1)+sum[l[rt]]-sum[l[lt]]; if(k<=tmp){ rx=mid; for(int i=L-1;i;i-=lowbit(i)) use[i]=l[use[i]]; for(int i=R;i;i-=lowbit(i)) use[i]=l[use[i]]; lt=l[lt];rt=l[rt]; } else{ lx=mid+1;k-=tmp; for(int i=L-1;i;i-=lowbit(i)) use[i]=r[use[i]]; for(int i=R;i;i-=lowbit(i)) use[i]=r[use[i]]; lt=r[lt];rt=r[rt]; } } return f[lx];}char op[5];int q[10005][4],t;int main(){ rd(t); while(t--){ rd2(n,m); for(int i=1;i<=n;i++) { rd(a[i]);f[i]=a[i]; } nn=n; for(int i=1;i<=m;i++){ scanf("%s",op); if(op[0]=='Q') { scanf("%d%d%d",&q[i][1],&q[i][2],&q[i][3]); q[i][0]=1; } else{ scanf("%d%d",&q[i][1],&q[i][2]); q[i][0]=0; f[++nn]=q[i][2]; } } sort(f+1,f+1+nn); nn=unique(f+1,f+1+nn)-f-1;//离散化线段树,并去重 tot=0; T[0]=0; build(0,1,nn); for(int i=1;i<=n;i++){ T[i]=tot+1; //T[i]记录第i个线段树的根 update(T[i-1],1,nn,h(a[i]),1); } for(int i=1;i<=n;i++) S[i]=T[0]; // int L,R,k,x; for(int i=1;i<=m;i++){ if(q[i][0]){ printf("%d\n",query(q[i][1],q[i][2],q[i][3])); } else{ add(q[i][1],h(a[q[i][1]]),-1); add(q[i][1],h(q[i][2]),1); a[q[i][1]]=q[i][2]; } } } return 0;}
0 0
- zoj-2112(主席树动态求区间第k小数)
- zoj 2112 树状数组 套主席树 动态求区间 第k个数
- ZOJ 2112 Dynamic Rankings 树状数组套主席树 单点修改求动态区间第K大
- zoj 2112 主席树+树状数组求动态第k大
- zoj 2112 Dynamic Rankings(主席树&动态第k大)
- ZOJ 2112 动态第k大 主席树+树状数组
- [BZOJ 1901][ZOJ 2112]Dynamic Rankings(树状数组套主席树、动态区间第k大值查询)
- 主席树 求区间第k大数(可修改)
- 主席树求静态区间第K大
- 主席树 --- 求区间第k大值
- 主席树详解 zoj 2112 (单点更新)+ poj 2104 区间第k大
- 【主席树】 ZOJ 2112 Dynamic Rankings 区间第k小值
- ZOJ 2112 Dynamic Rankings (主席树+单点修改,询问区间第K值)
- ZOJ 2112 & BZOJ 1901 Dynamic Rankings(主席树 单点更新 区间第K大)
- 动态区间第K大(树状数组+主席树)
- ZOJ 2112 Dynamic Rankings(动态求区间第k大+整体二分)
- 动态区间第K小数 分块/树套树
- ZOJ 2112 Dynamic Rankings(主席树-动态第k大)
- change Java on Ubuntu Kylin 15.04
- 黑马程序员—— Java 基础 面向对象之继承 (复习)
- 堆排序2.0
- POJ2503词典 Babelfish在外文中查找对应的英文
- 子父类中构造函数的特点
- zoj-2112(主席树动态求区间第k小数)
- UVA 11354 Bond(最小生成树+lca+倍增求祖先节点)
- 页面更新的问题
- 一次被黑追凶(未完待续)
- hdoj 1143 Tri Tiling 【递推】
- 链接MapReduce作业http://user.qzone.qq.com/1178772762/blog/1440417746
- Windows内核编程基础篇之字符串的拷贝
- Hbase优化
- 设置异常向量表