数据结构2 静态区间第K大/第K小
给定数组$A[1...N]$, 区间$[L,R]$中第$K$大/小的数的指将$A[L...R]$中的数从大到小/从小到大排序后的第$K$个.
"静态"指的是不带修改.
这个问题有多种做法:
1. 归并排序
POJ 2104, 静态区间第K小
#include <bits/stdc++.h>
using namespace std; const int N(1e5+);
int a[][N]; void merge(int id, int b, int e){
int mid=(b+e)>>;
for(int l=b, r=mid, i=b; i<e; i++){
if(l==mid) a[id][i]=a[id+][r++];
else if(r==e) a[id][i]=a[id+][l++];
else if(a[id+][l]<=a[id+][r]) a[id][i]=a[id+][l++];
else a[id][i]=a[id+][r++];
}
} void build(int id, int b, int e){
if(b+==e){
scanf("%d", a[id]+b);
return;
}
int mid=(b+e)>>;
build(id+, b, mid);
build(id+, mid, e);
merge(id, b, e);
}
//返回k在[l, r)与[L, R)交集上的Rank
int Rank(int id, int L, int R, int l, int r, int k){
if(l<=L&&R<=r){
return lower_bound(a[id]+L, a[id]+R, k)-a[id]-L;
}
int mid=(L+R)>>;
if(r<=mid){
return Rank(id+, L, mid, l, r, k);
}
if(l>=mid){
return Rank(id+, mid, R, l, r, k);
}
return Rank(id+, L, mid, l, r, k)+Rank(id+, mid, R, l, r, k);
}
//返回(l, r]中Rank(x)>=k的最小的x
int BS(int b, int e, int k, int n){
int l=-1e9-, r=1e9+, mid;
while(r-l>){
mid=(l+r)>>;
if(Rank(, , n, b, e, mid)>=k) r=mid;
else l=mid;
}
return r;
}
int main(){
int n, m; scanf("%d%d", &n, &m);
build(, , n);
for(int l, r, k; m--;){
scanf("%d%d%d", &l, &r, &k), l--;
printf("%d\n", BS(l, r, k, n)-);
}
}
这种做法的想法是将归并排序的过程记录下来, 这样就形成了一棵线段树, 这棵线段树的每个节点记录着它所代表的那个区间[L,R]排好序后的情形.
我们把这样的线段树称做归并排序树, 归并排序树能在$O(\log^2{N})$的复杂度内完成如下查询:
$\text{RANK}(l, r, x)$: 区间$[l,r]$内小于$x$的数的数目.
定义$\text{LEAST}(l, r, k)$为区间$[l,r]$上第$k$小的数, 则有
$\text{LEAST}(l, r, k) = \max \{x \mid \text{RANK}(l, r, x)<k\}$
因而对于询问$\text{LEAST}(l, r, x)$, 我们可以二分答案 $x$ + $\text{RANK}(l, r, x)$判断, 从而在$O(\log{M}\log^2{N})$的复杂度内完成查询, 其中$M$是元素的范围, $N$是区间总长度. 当然, 我们也可以现将数组$A[1\cdots N]$排序, 付出一个$O(N\log{N}$)的预处理复杂度, 然后便可做到单次查询$O(\log^3{N})$.
但我觉得这个复杂度还是太高了, (归并排序)这种做法应该还有优化的可能性, 有待研究.
2. 划分树
数据结构2 静态区间第K大/第K小的更多相关文章
- 无序数组求第k大/第k小的数
根据http://www.cnblogs.com/zhjp11/archive/2010/02/26/1674227.html 博客中所总结的7种解法,我挑了其中的解法3和解法6进行了实现. 解法3: ...
- POJ 2104 静态找区间第k大
静态区间第k大的问题,往往可以利用主席树来解决 这是主席树的第一道题 主席树大概可以理解为在n个节点上都建立一棵线段树,但是想想会超出内存 每一个节点保存的线段树都记录当前整段前缀区间的信息 但是因为 ...
- HDU3473--Minimum Sum(静态区间第k大)
Minimum Sum Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- 主席树初步学习笔记(可持久化数组?静态区间第k大?)
我接触 OI也快1年了,然而只写了3篇博客...(而且还是从DP跳到了主席树),不知道我这个机房吊车尾什么时候才能摸到大佬们的脚后跟orz... 前言:主席树这个东西,可以说是一种非常畸形的数据结构( ...
- poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 43315 Accepted: 14296 Ca ...
- 静态区间第k大(主席树)
POJ 2104为例(主席树入门题) 思想: 可持久化线段树,也叫作函数式线段树,也叫主席树(高大上). 可持久化数据结构(Persistent data structure):利用函数式编程的思想使 ...
- 静态区间第k大(归并树)
POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...
- 主席树学习笔记(静态区间第k大)
题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...
- 主席树(静态区间第k大)
前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...
随机推荐
- 【开源】分享一个前后端分离方案-前端angularjs+requirejs+dhtmlx 后端asp.net webapi
一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家.关于前后端分离这个话题大家也谈了很久了,希望我这个实践能对大家有点点帮助,演示和源码都贴在后面. 二.技术架构 这两年a ...
- Linq连接查询之左连接、右连接、内连接、全连接、交叉连接、Union合并、Concat连接、Intersect相交、Except与非查询
内连接查询 内连接与SqL中inner join一样,即找出两个序列的交集 Model1Container model = new Model1Container(); //内连接 var query ...
- BGP--边界网关协议
要全面了解BGP,首先我们要回答以下看上去很简单的问题:为什么需要BGP,也就是说BGP是如何产生的,它解决了什么问题.带着以上问题,我们先简单的回顾一个路由协议发展的轨迹. 首先路由的实质是描述一个 ...
- 分布式拒绝服务攻击 DDoS
分布式拒绝服务(DDoS:Distributed Denial of Service)攻击指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDoS攻击,从而成倍地提高拒 ...
- bloom filter
Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员. 结 构 二进制 召回率 ...
- <string> 与<string.h>、<cstring>的区别
<string.h> <string.h>是C版本的头文件,包含比如strcpy.strcat之类的字符串处理函数. <cstring> 在C++标准化(1998年 ...
- Bete冲刺第三阶段
Bete冲刺第三阶段 今日工作: web: 检索了各类资料,今日暂时顺利解决了hibernate懒加载异常的问题,采用的凡是也比较简单就是添加了一个OpenSessionInViewFilter的过滤 ...
- 如何录制手机屏幕并转成gif
因为上一篇博客需要展示一些软件操作过程,如果直接截图的话一来可能需要多张图,二来表达也不方便,所以特意去查了下如何录制手机屏幕操作,然后转成gif,嵌入进博客中,这样表达起来就方便多了.话不多说,总结 ...
- 时间复杂度---我又要想起初中数学老师的脸了xxxxx
时间复杂度: 常用的时间复杂度有:常数级,对数级,线性级 线性对数级 平方级,立方级别,多项式级别,指数级别,阶乘级别 这里我们主要探讨对数级,线性级,平方级,指数级---为什么不讨论其他的?别的我也 ...
- 100735G
很明显,我们构造出一个串后,无非就是两个结果:最长的是黑的,最长的是白的,因此选两个中小的就可以了 #include<iostream> using namespace std; int ...