hdu2665区间第K大+主席树解题报告
来源:互联网 发布:纹理过滤 三线性优化 编辑:程序博客网 时间:2024/06/15 00:41
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2665
多组数据的区间第k大 n<10^5
0x00:构造权值线段树
和普通线段树相似,每次插入 a[i] 时对下标为 a[i] 的位置加一,
这样做就可以用 O(log n) 的时间查询全局第k大了(但有可能要离散化)
0x01:可持续化线段树
可持续化线段树记录每一颗线段树的根,以保留所有的历史版本
除了第一次构造出整颗线段树之外,之后每一次只用将有改变的节点构造出来
其他节点均连接到上一个历史版本的相同位置
if (k <= mid)add(tr[now].ls = _new(),tr[old].ls,k,l,mid), tr[now].rs = tr[old].rs;// now -> 现在正在处理的位置 old -> 历史版本中的位置
0x02:构建主席树
主席树就是一颗可持续化线段树。
每插入一个 a[i] 都新建一个历史版本,时空复杂度都是 O(log n)
有些写法里要先构建一颗线段树,再在其上面增加历史版本
但其实是没有必要的(只针对此题,特殊情况另外讨论)
因为 tr[0] 的 左右儿子节点都是 0,tr[0] 可以说就是一颗无穷大的线段树
0x03:线段树相减
对于线段树的每一个节点,都记录着该点所对应区间有多少个 a[i]
因此,tree[r] - tree[l-1] 就可以得到对应区间有多少个 a[i] 在区间 [l,r] 中
即可查询区间第k大
0x04:代码实现:
这道题有多组数据
所以
一定要清空!!!
(hdu上看不到输入数据所以调了很久)
*主席树↓
#include <cstdio>#include <queue>#define N 200100#define mid ((l+r)>>1)using namespace std;int T,n,m,i,rt[N],tot,ans[N],a[N],rnk[N];struct point {int num,ls,rs;} tr[N << 4];priority_queue<pair<int,int> > q;inline int _new() {tr[++tot].num = 0; return tot;}void add(int now,int old,int k,int l,int r) { if (l == r) return void(++tr[now].num); if (k <= mid) add(tr[now].ls = _new(),tr[old].ls,k,l,mid), tr[now].rs = tr[old].rs; if (k > mid) add(tr[now].rs = _new(),tr[old].rs,k,mid+1,r), tr[now].ls = tr[old].ls; tr[now].num = tr[tr[now].ls].num + tr[tr[now].rs].num;}int ask(int nowl,int nowr,int k,int l,int r) { if (l == r) return l; if (tr[tr[nowr].ls].num - tr[tr[nowl].ls].num >= k) return ask(tr[nowl].ls,tr[nowr].ls,k,l,mid); return ask(tr[nowl].rs,tr[nowr].rs,k - (tr[tr[nowr].ls].num - tr[tr[nowl].ls].num),mid+1,r);}int main() { for (scanf("%d",&T);T--;tot = 0) { scanf("%d%d",&n,&m); for (i=1;i<=n;i++) { scanf("%d",a+i); q.push(make_pair(-a[i],i)); } for (i=1;i<=n;i++) { pair<int,int> tmp = q.top(); q.pop(); ans[rnk[tmp.second] = i] = -tmp.first; } for (i=1;i<=n;i++) add(rt[i] = _new(),rt[i-1],rnk[i],1,n); for (int l,r,k;m--;) { scanf("%d%d%d",&l,&r,&k); printf("%d\n",ans[ask(rt[l-1],rt[r],k,1,n)]); } }}
关于主席树的由来:
据说该算法的发明者是 HJT
阅读全文
0 0
- hdu2665区间第K大+主席树解题报告
- 主席树模板(区间第k大!)hdu2665
- 主席树(静态区间第k大)+poj2014+poj2761+hdu2665
- HDU2665 主席树原理解决静态区间第K大值问题总结 有详细图解和代码解释
- HDU2665(函数式线段树-区间第K大)
- poj2104 主席树区间第k大
- 主席树解决区间第k大
- 区间第k大(主席树)
- hdu2665 求区间第k大(小?)【主席树or可持久化线段树or函数式线段树】
- HDU2665 Kth number(区间第K大)
- poj 2104 区间第k大 主席树
- poj2761&&poj2104 主席树(静态区间第K大)
- hdu 2665 区间第K大 主席树入门
- 静态区间第k大(主席树)
- poj 2104 主席树(区间第k大)
- zoj2112 树状数组+主席树 区间动第k大
- 主席树求静态区间第K大
- POJ2104 POJ2761 区间第K大 主席树
- Switch games
- 快速幂 LightOJ 1282
- HDMI管脚定义
- 顺序表应用6:有序顺序表查询
- Java学习笔记之Hibernate-用注解方式实现多对多
- hdu2665区间第K大+主席树解题报告
- tomcat部署项目,jsp无法打开问题
- Red and Black
- electron + vue 实践项目
- 两粒种子,一片森林 jzoj 2017.8.22 B组
- HDMI之DDC通道
- 添加的依赖
- 多线程
- python: IO操作