静态区间第k大(主席树)
POJ 2104为例(主席树入门题)
思想:
可持久化线段树,也叫作函数式线段树,也叫主席树(高大上)。
可持久化数据结构(Persistent data structure):利用函数式编程的思想使其支持询问历史版本、同时充分利用它们之间的共同数据来减少时间和空间消耗。
主席树:对原序列的每一个前缀[1..i]建立出一棵线段树维护值域上每个数的出现次数(所以要先离散化)。线段树每个节点保存的是区间中前缀对应的值出现的次数。
注意:
- 这里没有使用指针,而是给每个节点编号,通过编号来将节点与左右子节点连接起来。
- 对于前缀[1,i]和前缀[1,i+1]的线段树,如果离散化后newa[i+1]<=mid ,那么这两棵线段树的右边是完全相同的,不需要重复建立。
- 查询过程,先查看左子树中元素的出现次数是否大于k,如果是,继续查左子树,反之查询右子树。
- 同一区间出现次数可以直接相减得到。
代码:
#include<cstdio>
#include<algorithm>
using namespace std;//[]
const int maxn = 100010, maxm = 20 * maxn;
int tot, c;
int a[maxn], newa[maxn];
int lson[maxm], rson[maxm], t[maxm], tree[maxm];
//lson,rson记录左右节点标号,t记录每一个前缀构成的线段树的根节点标号,tree记录标号对应区间中数字出现次数
int compress(int x)//离散化
{
return lower_bound(newa+1, newa+1+c, x) - newa;
}
int build(int l, int r)
{
int root = tot++; tree[root] = 0;
int mid = (l+r)/2;
if(l == r ) return root;
lson[root] = build(l, mid);
rson[root] = build(mid + 1, r);
return root;
}
void update(int root, int newroot, int l, int r, int num)
{
tree[newroot] = tree[root] + 1;
if(l == r) return;
int mid = (l + r)/2;
if(num <= mid){
lson[newroot] = tot++;//有变动,重新建立
rson[newroot] = rson[root];//右边不变
update( lson[root], lson[newroot], l, mid, num);
}else{
rson[newroot] = tot++;//有变动,重新建立
lson[newroot] = lson[root];//左边不变
update(rson[root], rson[newroot], mid + 1, r, num);
}
}
int query(int leftroot, int rightroot, int l, int r, int k)
{
if(l == r ) return l;
int mid = (l + r)/2;
if(tree[lson[rightroot]] - tree[lson[leftroot]] >= k){
query(lson[leftroot], lson[rightroot], l, mid, k);
}else{
int temp = tree[lson[rightroot]] - tree[lson[leftroot]];
query(rson[leftroot], rson[rightroot], mid + 1, r, k - temp);
}
}
int main (void)
{
int n,m;scanf("%d%d",&n,&m);
tot = 0;
for(int i = 1; i <= n; i++) {
scanf("%d",&a[i]);
newa[i] = a[i];
}
sort(newa+1, newa+1+n);
c = unique(newa+1, newa+1+n) - newa-1;//去重
t[0] = build(1, c);//初始化
for(int i = 1; i <= n; i++){
t[i] = tot++;
update(t[i-1], t[i], 1 , c, compress(a[i]));//不断更新,建树
}
int l, r, k;
while(m--){
scanf("%d%d%d",&l,&r,&k);
printf("%d\n", newa[query(t[l-1], t[r], 1 ,c, k)]);
}
return 0;
}//1800ms
还是划分树快些。。。
真的是理解花了好久,连写再调试又花了好久。。。。。。然而只学了点毛皮。
动态区间第k大貌似要用到树状数组,过几天再来研究一下!
静态区间第k大(主席树)的更多相关文章
- HDU2665 求区间第K大 主席树
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2665 代码: //#include<bits/stdc++.h> #include< ...
- POJ-2104-K-th Number(区间第K大+主席树模板题)
Description You are working for Macrohard company in data structures department. After failing your ...
- poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 43315 Accepted: 14296 Ca ...
- 可持久化线段树(主席树)——静态区间第k大
主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...
- 主席树(静态区间第k大)
前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- 静态区间第k大(归并树)
POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...
- HDU3473--Minimum Sum(静态区间第k大)
Minimum Sum Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- 主席树学习笔记(静态区间第k大)
题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...
- HDU 2665 Kth number(主席树静态区间第K大)题解
题意:问你区间第k大是谁 思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的. 具体可以看q学姐的B站视频 代码: #include<cmath> #i ...
随机推荐
- 自动判断手机版和pc版
<html><head><title>欢迎来到手机版</title><script>var ua = navigator.userAgent ...
- Java实现求二叉树的路径和
题: 解: 这道题考的是如何找出一个二叉树里所有的序列. 我的思路是先从根节点开始遍历,找出所有的子节点,因为每个子节点只有一个父节点,再根据每个子节点向上遍历找出所有的序列,再判断序列的总和. 这样 ...
- Effective Java读书笔记完结啦
Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...
- Android 中保存数据到文件中
1.在安卓开发中,会遇到保存数据到手机中以及从手机中获取数据的情况 /** * 把数据存放到手机内存中 * * @param number * @param password * @return */ ...
- php接收json格式数据(text/xml)
在API服务中,目前流行采用json形式来交互. 给前端调用的接口输出Json数据,这个比较简单,只需要组织好数据,用json_encode($array) 转化一下,前端就得到json格式的数据. ...
- 【PostgreSQL-9.6.3】Red Hat 4.4.7下的安装
1. 下载源码包https://www.postgresql.org/ftp/source/v9.6.1/ 2. 上传到/opt目录下 3. 创建postgres用户及dba组,并修改压缩包的属主属组 ...
- UVALive 4128 Steam Roller 蒸汽式压路机(最短路,变形) WA中。。。。。
题意: 给一个由n*m个正方形格子组成的矩形,其中每个格子的边都是可以走的,长度给定,规定:如果在进入该路前需要拐弯,或者走完该路需要拐弯,都是需要付出双倍距离的(每条路最多算2倍).问从起点到终点的 ...
- matlab中数据类型
在MATLAB中有15种基本数据类型,分别是8种整型数据.单精度浮点型.双精度浮点型.逻辑型.字符串型.单元数组.结构体类型和函数句柄.这15种基本数据类型具体如下. 有符号整数型:int8,int1 ...
- [转]c++应用程序文件的编译过程
原文地址 这里讲下C++文件的编译过程及其中模板的编译过程: 一:一般的C++应用程序的编译过程. 一般说来,C++应用程序的编译过程分为三个阶段.模板也是一样的. 在cpp文件中展开inclu ...
- CAD控件,CAD插件使用教程:Android开发使用控件--开发环境的搭建
Android开发使用控件入门--环境搭建 2014-12-24 09:57 14人阅读 评论(0) 收藏 编辑 删除 CAD控件.CAD三维控件,手机 ...