K-th Number
Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 35653   Accepted: 11382
Case Time Limit: 2000MS

Description

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 109 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

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

Sample Output

  1. 5
  2. 6
  3. 3

Hint

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

Source

Northeastern Europe 2004, Northern Subregion

 
  划分树,经典题
  关于划分树的解释可以参考博文:sdut 2610:Boring Counting(第四届山东省省赛原题,划分树 + 二分)。这个属于高级点的应用,至于基础的介绍,我就不多写了(懒人一个。。),可以参考这篇博客,介绍的很详细:划分树
  这里简单一提,划分树的主要作用是用来求“区间内第k大的元素”,这道题属于经典应用,就是赤裸裸的求一个区间内第k大的数。题目“K-th Number”已经标明了这种含义。
  因为之前做过一道划分树的题,所以无耻的套用了上道题的代码,然后就改了改就无耻的过了。O_o,原谅我吧。
  代码
  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <algorithm>
  4. using namespace std;
  5. #define MAXN 100005
  6. struct Divide_tree{ //划分树的结构(4个数组,2个操作)
  7. int arr[MAXN]; //原数组
  8. int sorted[MAXN]; //排序后数组
  9. int sum[][MAXN]; //记录第i层1~j划分到左子树的元素个数(包括j)
  10. int dat[][MAXN]; //记录第i层元素序列
  11. void build(int c,int L,int R) //建树,主要是建立sum[][]和dat[][]数组
  12. {
  13. int mid = (L+R)>>;
  14. int lsame = mid-L+; //lsame用来记录和中间值val_mid相等的,且可以分到左孩子的数的个数
  15. //简单来说就是可以放入左孩子的,与中间值val_mid相等的数的个数
  16. int lp=L,rp=mid+; //当前节点的左孩子和右孩子存数的起点
  17. for(int i=L;i<mid;i++) //获得一开始的lsame
  18. if(sorted[i]<sorted[mid])
  19. lsame--;
  20. for(int i=L;i<=R;i++){ //从前往后遍历一遍,
  21. //确定当前节点区间内的所有元素的归属(放在左孩子或者放在右孩子)
  22. if(i==L) sum[c][i]=;
  23. else sum[c][i]=sum[c][i-];
  24. if(dat[c][i]<sorted[mid]){ //当前元素比中间值val_mid小,放入左孩子
  25. dat[c+][lp++] = dat[c][i];
  26. sum[c][i]++;
  27. }
  28. else if(dat[c][i]>sorted[mid]) //当前元素比中间值val_mid大,放入右孩子
  29. dat[c+][rp++] = dat[c][i];
  30. else{ //当前元素值与中间值val_mid相等,根据lsame数判断放入左孩子还是右孩子
  31. if(lsame){
  32. lsame--;
  33. sum[c][i]++;
  34. dat[c+][lp++]=sorted[mid];
  35. }
  36. else{
  37. dat[c+][rp++]=sorted[mid];
  38. }
  39. }
  40. }
  41. if(L==R) return ; //递归出口,遇到叶子节点
  42. build(c+,L,mid); //递归进入左孩子区间
  43. build(c+,mid+,R); //递归进入右孩子区间
  44. }
  45. int query(int c,int L,int R,int ql,int qr,int k)
  46. {
  47. //c为树的层数,L,R为当前节点的区间范围,ql,qr为查询的区间范围,k为查询范围内第k大的数
  48. if(L==R) //递归出口,返回第k大的数
  49. return dat[c][L];
  50. int s; //记录[L,ql-1]中进入左孩子的元素的个数
  51. int ss; //记录[ql,qr]中进入左孩子的元素的个数
  52. int mid=(L+R)>>;
  53. if(L==ql){ //端点重合的情况,单独考虑
  54. s=;
  55. ss=sum[c][qr];
  56. }
  57. else {
  58. s=sum[c][ql-];
  59. ss=sum[c][qr]-s;
  60. }
  61. if(k<=ss) //左孩子的元素个数大于k个,说明第k大的元素一定在左孩子区间中,到左孩子中查询
  62. return query(c+,L,mid,L+s,L+s+ss-,k);
  63. else
  64. return query(c+,mid+,R,mid++ql-s-L,mid++qr-s-ss-L,k-ss);
  65. }
  66. };
  67. Divide_tree tree; //定义划分树
  68. int main()
  69. {
  70. int i,L,R,N,M,k;
  71. scanf("%d%d",&N,&M);
  72. for(i=;i<=N;i++){ //输入
  73. scanf("%d",&tree.arr[i]);
  74. tree.sorted[i]=tree.dat[][i]=tree.arr[i];
  75. }
  76. sort(tree.sorted+,tree.sorted+N+);
  77. tree.build(,,N);
  78. for(i=;i<=M;i++){ //M次询问
  79. scanf("%d%d%d",&L,&R,&k);
  80. printf("%d\n",tree.query(,,N,L,R,k));
  81. }
  82.  
  83. return ;
  84. }

poj 2104:K-th Number(划分树,经典题)的更多相关文章

  1. 【POJ 2104】 K-th Number 主席树模板题

    达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没 ...

  2. POJ2104 K-th Number 划分树 模板题啊

    /*Source Code Problem: 2104 User: 96655 Memory: 14808K Time: 1282MS Language: G++ Result: Accepted S ...

  3. poj 2104 K-th Number 划分树,主席树讲解

    K-th Number Input The first line of the input file contains n --- the size of the array, and m --- t ...

  4. [hdu2665]Kth number(划分树求区间第k大)

    解题关键:划分树模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cs ...

  5. 静态区间第k大(划分树)

    POJ 2104为例[经典划分树问题] 思想: 利用快速排序思想, 建树时将区间内的值与区间中值相比,小于则放入左子树,大于则放入右子树,如果相等则放入左子树直到放满区间一半. 查询时,在建树过程中利 ...

  6. HDU-2665-Kth number(划分树)

    Problem Description Give you a sequence and ask you the kth big number of a inteval.   Input The fir ...

  7. [NBUT 1458 Teemo]区间第k大问题,划分树

    裸的区间第k大问题,划分树搞起. #pragma comment(linker, "/STACK:10240000") #include <map> #include ...

  8. poj 2104 K-th Number (划分树入门 或者 主席树入门)

    题意:给n个数,m次询问,每次询问L到R中第k小的数是哪个 算法1:划分树 #include<cstdio> #include<cstring> #include<alg ...

  9. POJ 2104 K-th Number(划分树)

    题目链接 参考HH大神的模版.对其中一些转移,还没想清楚,大体明白上是怎么回事了,划分树就是类似快排,但有点点区别的.多做几个题,慢慢理解. #include <cstdio> #incl ...

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

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

随机推荐

  1. HDU 1003 动态规划

    http://acm.hdu.edu.cn/showproblem.php?pid=1003 这几天开始刷动归题目,先来一道签到题 然而做的并不轻松, 没有注意到边界问题, WA了几发才发现 #inc ...

  2. tfw格式图解

    话不多说,直接看图. 上图中的UV坐标,实际上只的是图像的 横向坐标 和 纵向坐标 .即图像的行和列坐标. 对于图上任意一个像素点(col,row)这个坐标,换算其地理坐标就十分简单. GeoX = ...

  3. fastx_toolkit软件使用说明

    高通量测序数据下机后的原始fastq文件,包含4行,其中一行为质量值,另外一行则为对应序列,我们都了解高通量的数据处理首先要进行质量控制,这些过程包括去接头.过滤低质量reads.去除低质量的3'和5 ...

  4. Droid4x快照还原

    一.问题描述 1. Droid4x还原快照可以通过VirtualBox 先还原快照 2. virtualbox 还原快照之后 如果没有用virtualbox启动 并关闭     而是直接启动Droid ...

  5. webrtc开源项目音频重采样“不友好接口”的几点总结

    WebRTC(Web Real Time Communication)并不是Google原来自己的技术,在2010年,Google以大约6820万美元收购了VoIP软件 开发商Global IP So ...

  6. history/location操作 /navigator 操作/ screen操作

    话说mac真的没广告...就凭这点,mac完胜.ei capitan 好牛畅,分屏很好用啊,回不去了. var hist=window.history; hist.go(param); // para ...

  7. poj 1789

    http://poj.org/problem?id=1789 这是一道图论的题,个人觉得和那个POJ1258是差不多的,就是多了一步,题目难以读懂 题目的意思:就是给你一群字符串要你找字符串对应的字符 ...

  8. linux多线程下载工具mwget

    linux多线程下载工具mwget 经常使用wget进行文件下载,然而wget的处理速度并不如人意.遇到一些国外的站点,经常慢得像蜗牛一般.然而为了解决这个问题,便有了mwget:m表示multi多线 ...

  9. jquery UI 弹出框

    2015-07-17 11:04:38 <div id="reg"></div> <script type="text/javascript ...

  10. ACM/ICPC 之 数论-费马大定理(HNUOJ 13371)

    好歹我是数学专业的学生,还是要写写训练的时候遇到的数学问题滴~~ 在ACM集训的时候在各高校OJ上也遇见过挺多的数学问题,例如大数的处理,素数的各种算法,几何问题,函数问题(单调,周期等性质),甚至是 ...