K-th Number
You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. 
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" 
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

Input

The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000). 
The second line contains n different integer numbers not exceeding 10 9 by their absolute values --- the array for which the answers should be given. 
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

Output

For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

Sample Input

7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3

Sample Output

5
6
3

Hint

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.
 
 
题解:
以前用主席树写过,现在学习了一下划分树。

划分树,类似线段树,主要用于求解某个区间的第k 大元素(时间复杂度log(n)),快排本也可以快速找出,但快排会改变原序列,所以每求一次都得恢复序列。

  下面就以 POJ 2104 进行解说:

  题目意思就是,给你n 个数的原序列,有m 次询问,每次询问给出l、r、k,求原序列l 到r 之间第k 大的数。n范围10万,m范围5千,这道题用快排也可以过,快排过的时间复杂度n*m,而划分树是m*logn(实际上应该是nlogn才对,因为建图时间是nlogn,n又比m大),分别AC后,时间相差很明显。

  划分树,顾名思义是将n 个数的序列不断划分,根结点就是原序列,左孩子保存父结点所有元素排序后的一半,右孩子也存一半,也就是说排名1 -> mid的存在左边,排名(mid+1) -> r 的存在右边,同一结点上每个元素保持原序列中相对的顺序。见下图:

   

  红点标记的就是进入左孩子的元素。

  当然,一般不会说每个结点开个数组存数,经观察,每一层都包含原本的n 个数,只是顺序不同而已,所以我们可以开val[20][N]来保存,也就是说共20层,每一层N个数。

  我们还需要一个辅助数组num,num[i]表示i 前面有多少数进入左孩子(i 和i 前面可以弄成本结点内也可以是所有,两种风格不同而已,下面采取的是本结点内),和val一样,num也开成num[20][N],来表示每一层,i 和i 前面(本结点)有多少进入左孩子。

  第一层:1 进入左孩子,num[1]=1,5 进入右孩子,num[2]=1,...,num[8]=4。

  第二层:5 进入左孩子,num[5]=1,6 进入右孩子,num[6]=1,...,num[8]=2。

  建图时就是维护每一层val[]和num[]的值就可以了。

很是清晰的,

最后那个询问其实不难,自己一开始瞎比比了一会,卡了许久时间。

    这样子转换一下,多仔细考虑转换l,r那一段。

 #include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio> #define N 100007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if (ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m;
int a[N],val[][N],num[][N]; void build(int deep,int l,int r)
{
if (l==r) return;
int mid=(l+r)>>,same=mid-l+;
for (int i=l;i<=r;i++)
if (val[deep][i]<a[mid]) same--;
int lh=l,rh=mid+;
for (int i=l;i<=r;i++)
{
if (i==l) num[deep][i]=;
else num[deep][i]=num[deep][i-];
if (val[deep][i]<a[mid] || val[deep][i]==a[mid]&&same>)//没有same那么所以有和a[mid]一样大的树都会进入做子树
{
val[deep+][lh++]=val[deep][i];
num[deep][i]++;
if (val[deep][i]==a[mid]) same--;
}
else val[deep+][rh++]=val[deep][i];
}
build(deep+,l,mid),build(deep+,mid+,r);
}
int query(int deep,int l,int r,int x,int y,int k)
{
if (l==r) return val[deep][l];
int ly,mid=(l+r)>>;
if (x==l) ly=;
else ly=num[deep][x-];
int sum=num[deep][y]-ly;//表示放在左边有多少。
if (sum>=k) return query(deep+,l,mid,l+ly,l+num[deep][y]-,k);//转换到这一段区间放入做子树的那一段。
else
{
int lr=mid++(x-l-ly);
return query(deep+,mid+,r,lr,lr+y-x+-sum-,k-sum);
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for (int i=;i<=n;i++)
a[i]=read(),val[][i]=a[i];
sort(a+,a+n+);
build(,,n);
for (int i=;i<=m;i++)
{
int l=read(),r=read(),k=read();
printf("%d\n",query(,,n,l,r,k));
}
}
}

K-th Number POJ - 2104 划分树的更多相关文章

  1. K-th Number Poj - 2104 主席树

    K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...

  2. poj 2104 划分树

    思路:裸的划分树 #include<iostream> #include<algorithm> #include<cstring> #include<cstd ...

  3. hdu 4417,poj 2104 划分树(模版)归并树(模版)

    这次是彻底把划分树搞明确了,与此同一时候发现了模版的重要性.敲代码一个字符都不能错啊~~~ 划分树具体解释:点击打开链接 题意:求一组数列中随意区间不大于h的个数. 这个题的做法是用二分查询  求给定 ...

  4. 主席树 【权值线段树】 && 例题K-th Number POJ - 2104

    一.主席树与权值线段树区别 主席树是由许多权值线段树构成,单独的权值线段树只能解决寻找整个区间第k大/小值问题(什么叫整个区间,比如你对区间[1,8]建立一颗对应权值线段树,那么你不能询问区间[2,5 ...

  5. K-th Number POJ - 2104

    K-th Number POJ - 2104 You are working for Macrohard company in data structures department. After fa ...

  6. HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. hdu 2665 Kth number (poj 2104 K-th Number) 划分树

    划分树的基本功能是,对一个给定的数组,求区间[l,r]内的第k大(小)数. 划分树的基本思想是分治,每次查询复杂度为O(log(n)),n是数组规模. 具体原理见http://baike.baidu. ...

  8. [poj 2104]主席树+静态区间第k大

    题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即 ...

  9. poj 2104 主席树(区间第k大)

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

随机推荐

  1. 大小写 unix and windows

    如果你没有使用工具, 只是sqlplus对大小写不敏感. 如果你要给sql传递参数,且在windows下面就不需要考虑.如果是aix系统,最好写一样.

  2. 转】R利剑NoSQL系列文章 之 Cassandra

    原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/3/ 感谢! R利剑NoSQL系列文章 之 Cassandr ...

  3. AngularJS入门 & 分页 & CRUD示例

    一.AngularJS 简介 ​ AngularJS  诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前端JS框架,已经被用于Google的多款产品当中. ...

  4. Python 设计模式--简单工厂模式

    简单工厂模式(Factory Pattern)是一种创建型的设计模式,像工厂一样根据要求生产对象实例. 特点:根据不同的条件,工厂实例化出合适的对象. <大话设计模式>中实例:四则运算计算 ...

  5. vue-router之 beforeRouteEnter

    beforeRouteEnter在每次路由切换都执行 ,而项目优化后,切换路由mounted只在最开始执行一次 beforeRouteEnter的具体用法可参考官方文档 https://cn.vuej ...

  6. iOS Programming Web Services and UIWebView

    iOS Programming Web Services and UIWebView The work is divided into two parts. The first is connecti ...

  7. JavaScript——blob、file、flieReader、createObjectURL

    https://blog.csdn.net/opengl_es/article/details/44336477 https://www.cnblogs.com/hhhyaaon/p/5928152. ...

  8. [6818开发板]八核开发板|4G开发板|GPS开发板|嵌入式开发平台

    IMX6开发板(基本型):960元 IMX6开发板(豪华型):1460元 S5P4418 核心板可以无缝支持核心系统S5P6818,并保持底板设计不变,将兼顾更高端 的应用领域,为项目和产品提供更好的 ...

  9. laravel学习:模块化caffeinated

    # Modules Extract and modularize your code for maintainability. Essentially creates "mini-larav ...

  10. 5-Java-C(调和级数)

    题目描述: 1/1 + 1/2 + 1/3 + 1/4 + ... 在数学上称为调和级数. 它是发散的,也就是说,只要加上足够多的项,就可以得到任意大的数字. 但是,它发散的很慢: 前1项和达到 1. ...