POJ 2104为例

思想:

利用归并排序的思想:

  • 建树过程和归并排序类似,每个数列都是子树序列的合并与排序。
  • 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数,否则递归的对子树进行求解并相加。
  • 使用STL中的merge对子序列进行合并及排序。
  • 时间复杂度O(nlogn+mlog3n)

代码(vector实现):

#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;//[)
const int maxn = 1000010;
vector<int>dat[maxn*3];
int sorted[maxn], a[maxn];
void build(int k, int l, int r)
{
if(r - l == 1) dat[k].push_back(a[l]);
else {
int lch = 2 * k + 1, rch = 2 * k + 2;
build(lch, l, (l + r)/2);
build(rch, (l + r)/2, r);
dat[k].resize(r - l);
merge(dat[lch].begin(), dat[lch].end(), dat[rch].begin(), dat[rch].end(),dat[k].begin());
}
}
int query(int l, int r, int x, int k, int L, int R)
{
if(r <= L|| l >= R) return 0;//不相交
else if(l <= L && R <= r){//完全包含
return lower_bound(dat[k].begin(), dat[k].end(), x) - dat[k].begin();
}
else {
int lch = 2 * k + 1, rch = 2 * k + 2;
int lsum = query(l, r, x, lch, L, (L + R)/2);
int rsum = query(l, r, x, rch, (L + R)/2, R);
return lsum + rsum;
}
}
int main (void)
{
int n, m;scanf("%d%d",&n,&m);
for(int i = 0; i < n; i++){
scanf("%d",&a[i]);
sorted[i] = a[i];
}
sort(sorted, sorted+n);
build(0, 0, n);
int tl, tr, k;
while(m--){
scanf("%d%d%d",&tl,&tr,&k);
int l = 0, r = n;
while(r - l >1){
int mid = l + (r - l)/2;
int c = query(tl-1, tr, sorted[mid], 0, 0 ,n);
if(c <= k - 1 ) l = mid;
else r = mid;
}
printf("%d\n", sorted[l]);
}
return 0;
}//6000+ms

代码(数组实现):

#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;//[)
const int maxn = 1000010;
int dat[20][3*maxn];
int sorted[maxn], a[maxn];
void build(int p, int l, int r)
{
if(r - l == 1) dat[p][l] = a[l];
else {
build(p+1, l, (l + r)/2);
build(p+1, (l + r)/2, r);
merge(dat[p+1] + l, dat[p+1] + (l + r)/2, dat[p+1] + (l + r)/2, dat[p+1] + r, dat[p]+l);
}
}
int query(int l, int r, int x, int p, int L, int R)
{
if(r <= L|| l >= R) return 0;//不相交
else if(l <= L && R <= r){//完全包含
return lower_bound(dat[p]+L, dat[p]+R, x) - (dat[p]+L);
}
else {
int lsum = query(l, r, x, p+1, L, (L + R)/2);
int rsum = query(l, r, x, p+1, (L + R)/2, R);
return lsum + rsum;
}
}
int main (void)
{
int n, m;scanf("%d%d",&n,&m);
for(int i = 0; i < n; i++){
scanf("%d",&a[i]);
sorted[i] = a[i];
}
sort(sorted, sorted+n);
build(0, 0, n);
int tl, tr, k;
while(m--){
scanf("%d%d%d",&tl,&tr,&k);
int l = 0, r = n;
while(r - l >1){
int mid = l + (r - l)/2;
int c = query(tl-1, tr, sorted[mid], 0, 0 ,n);
if(c <= k - 1 ) l = mid;
else r = mid;
}
printf("%d\n", sorted[l]);
}
return 0;
}//2000+ms
  • 数组实现的要比vector快很多。
  • 归并树需要二分求解,但是划分树并不需要。因为划分树是从上到下,每次都用数组记录划分到左子树的元素个数,所以可以直接求得区间第k大数,而归并树是由下到上,每次对子树进行简单的合并和排序,并没有对划分到左子树的元素进行追踪,所以需要二分搜索答案,即线段树+二分。所以在求静态区间第k大时划分树也就比归并树要快。

静态区间第k大(归并树)的更多相关文章

  1. poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 43315   Accepted: 14296 Ca ...

  2. 主席树(静态区间第k大)

    前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...

  3. 可持久化线段树(主席树)——静态区间第k大

    主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...

  4. HDU3473--Minimum Sum(静态区间第k大)

    Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  5. 主席树学习笔记(静态区间第k大)

    题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...

  6. POJ2104-- K-th Number(主席树静态区间第k大)

    [转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249 无修改的区间第K大 我们先考虑简化的问题:我们要询问整个区间内的第K大.这样我们对值域建线段 ...

  7. HDU 2665 Kth number(主席树静态区间第K大)题解

    题意:问你区间第k大是谁 思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的. 具体可以看q学姐的B站视频 代码: #include<cmath> #i ...

  8. 主席树初步学习笔记(可持久化数组?静态区间第k大?)

    我接触 OI也快1年了,然而只写了3篇博客...(而且还是从DP跳到了主席树),不知道我这个机房吊车尾什么时候才能摸到大佬们的脚后跟orz... 前言:主席树这个东西,可以说是一种非常畸形的数据结构( ...

  9. POJ 2104 && POJ 2761 (静态区间第k大,主席树)

    查询区间第K大,而且没有修改. 使用划分树是可以做的. 作为主席树的入门题,感觉太神奇了,Orz /* *********************************************** ...

随机推荐

  1. Docker安装jenkins(六)

    这里是在linux环境下安装docker之后,在doucer内安装jenkins --------------------docker 安装 jenkins---------------------- ...

  2. iOS 中集成百度echarts3.0

    突然项目中要用到图表,所以就用了百度的echarts,然后就是网上搜了一下,由于本人的JS不是很熟悉,但是研究了一下还是做出来了,其实也不是很难 最后做的效果大概如下图这种,由于界面上没调整,所以粗糙 ...

  3. linux下mysql开启可访问

    修改mysql配置连接信息 将bind-address注释 vim /etc/my.cnf 修改mysql用户授权 mysql>GRANT ALL PRIVILEGES ON *.* TO ' ...

  4. 从0开始搭建SQL Server 2012 AlwaysOn 第二篇(配置故障转移集群)

    本篇主要讲配置Windows 故障转移集群及遇到的相关问题(坑),因为AlwaysOn是基于Windows的故障转移集群的 在讲解步骤之前需要了解一下故障转移集群仲裁配置 四种集群的仲裁配置: 1.多 ...

  5. 关于ubuntu16.04系统无法系统更新的解决

    1.提示系统更新升级,报错 /boot空间不足 2.根据网络,为获得/boot 空间,选择删除多余的内核文件 2.1 查询系统当前内核 ~$dpkg --get-selections |grep li ...

  6. Ubuntu Linux14 64位下在Android studio下用gradle编译Andrid项目时发生libz.so.1共享库找不到的解决方法。

    ---恢复内容开始--- 我在Ubuntu14 64为下安装了AS,但在用Gradle编译项目时总是报找不到 libz.so.1的错误. error while loading shared libr ...

  7. 迅为iTOP-4418开发板串口虚拟控制台配置为普通串口

    如何将 iTOP-4418 的串口控制台配置为普通串口.在最终的产品中,如果需要额外的串口,可以将调试用的控制台串口作为普通串口使用,因为交付给最终用户手中的产品,一般不需要调试串口.屏蔽串口控制台需 ...

  8. ssh设置免秘钥登录

    系统:CentOS7.2 需求:A服务器的fab用户需要使用www用户免秘钥登录到B服务器 换句话说,就是在A服务器的fab用户下,ssh    www@B服务ip   -p  端口  ,然后登录过去 ...

  9. error while loading shared libraries: libclntsh.so.11.1

    解决这个问题有两种方法 1.在当前用户下,添加链接库所在路径 LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH; export LD_LIBRARY_ ...

  10. python3+beautifulSoup4.6抓取某网站小说(二)基础功能设计

    本章学习内容:1.网页编码还原读取2.功能设计 stuep1:网页编码还原读取 本次抓取对象: http://www.cuiweijuxs.com/jingpinxiaoshuo/ 按照第一篇的代码来 ...