可修改区间k-th number
来源:互联网 发布:如何安装ubuntu虚拟机 编辑:程序博客网 时间:2024/06/06 09:00
不带修改的区间k-th number
这个众所周知了。可以用主席树实现。
具体的话其实就是开
我们在权值线段树上记录该范围数的出现次数,然后可以发现查询的两个区间端点的线段树信息可以相减,于是就可以线段树上二分了。时间复杂度
可修改区间k-th number
%了一波Samjia2000
注意到像上面那样做的话,修改一个点就要把它后面所有点也一起修改,显然TLE。
上面的方法是不能兹瓷修改的。
那我们就需要树套树!
修改操作
我们用一个BIT,BIT上的每个点都是一棵线段树,位置为
(请注意,主席树是真实的前缀和,而用树状数组则是伪前缀和)
修改操作,就在BIT上往后跳,跳到一个点就改一个点。
修改操作,就是BIT套线段树。
单次修改时间复杂度为
查询操作
有了记录前缀信息的BIT,就能像BIT一样,往前跳。
起初我以为要把所有这些线段树合并到答案里,但这样做麻烦,而且时间很慢。
其实可以先记录好所需的线段树的编号,然后直接进入线段树,在线段树里再把记录的编号拿出来,两个端点相减二分。当在线段树里二分时,所记录的编号里面的所有点也要相应地走到左儿子或右儿子。
查询操作,就是线段树套BIT。
单次查询时间复杂度为
总结
总的时间复杂度为
空间复杂度为
Code
#include<cstdio>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;const int N=10010,M=2000010;int n,m,num,a[N],lv[N],rv[N],root[N],ls[M],rs[M],sum[M];int lowbit(int x){return x&-x;}void modify(int &v,int l,int r,int x,int p)//single point modify{ if(!v) v=++num; sum[v]+=p; if(l==r) return; int mid=(l+r)>>1; if(x<=mid) modify(ls[v],l,mid,x,p); else modify(rs[v],mid+1,r,x,p);}void add(int x,int y,int p){ for(;x<=n;x+=lowbit(x)) modify(root[x],1,n,y,p);}void turnL(){ fo(i,1,rv[0]) rv[i]=ls[rv[i]]; fo(i,1,lv[0]) lv[i]=ls[lv[i]];}void turnR(){ fo(i,1,rv[0]) rv[i]=rs[rv[i]]; fo(i,1,lv[0]) lv[i]=rs[lv[i]];}int query(int l,int r,int k)//k-th number{ if(l==r) return l; int mid=(l+r)>>1,t=0; fo(i,1,rv[0]) t+=sum[rs[rv[i]]]; fo(i,1,lv[0]) t-=sum[rs[lv[i]]]; if(t>=k) { turnR(); return query(mid+1,r,k); } else { turnL(); return query(l,mid,k-t); }}int main(){ int tp,_,x,y,k; scanf("%d",&n); fo(i,1,n) { scanf("%d",&a[i]); add(i,a[i],1); } scanf("%d",&_); while(_--) { scanf("%d %d %d",&tp,&x,&y); if(tp==0) { add(x,a[x],-1); a[x]=y; add(x,a[x],1); } else { scanf("%d",&k); lv[0]=rv[0]=0; for(int i=y;i;i-=lowbit(i)) rv[++rv[0]]=root[i]; for(int i=x-1;i;i-=lowbit(i)) lv[++lv[0]]=root[i]; //record position in BIT printf("%d\n",query(1,n,k)); } } return 0;}
1 0
- 可修改区间k-th number
- POJ2104-K-th Number-区间第k大-可持久化线段树/主席树
- POJ 2104 K-th Number 区间第K大,可持久化线段树
- [POJ 2104]K-th Number (不带修改的区间k大,函数式线段树)
- POJ-2104 K-th Number (主席树 不带修改区间第k大)
- poj2104 K-th Number(静态区间k大,主席树)
- poj2140 K-th Number(静态区间第 k 大)
- POJ 2104 K-th Number (可持久化线段树)
- [poj]-2104-K-th Number-可持久化线段树
- poj 2104 K-th Number 可持久化线段树
- POJ 2104 K-th Number(可持久化线段树)
- POJ 2104 K-th Number 可持久化线段树
- poj2104 K-th Number 离散+可持久化线段树
- Pku2104 k - th number
- [poj2104]K-th Number
- [Poj2104]K-th Number
- [POJ2104]K-th Number
- poj2104 K-th Number
- OSI模型
- PHP之输入含数字的字符串在 所有数字前加%输出
- Android——实现无障碍
- 在SrollView中嵌套GridView
- web中的路径匹配
- 可修改区间k-th number
- CSS后代选择器
- 这段时间使用MKMapView的一点总结(待编辑)
- android 真机 访问本地web服务器 localhost
- SpringMVC Controller介绍及常用注解
- LeetCode之二叉树中序迭代遍历
- 简谈Masnory的功能和使用
- AVAssetExportSession progress KVO
- 帧率、码流与分辨率相关知识