又是不带修改的区间第k大,这次用的是一个不同的方法,划分树,划分树感觉上是模拟了快速排序的过程,依照pivot不断地往下划分,然后每一层多存一个toleft[i]数组,就可以知道在这一层里从0到i里有多少个被划分到了左子树,知道区间有多少个被分到左子树,就可以一路递归下去,不需要像函数式线段数一样,二分再加query,所以每次询问的复杂度也只是O(nlogn),空间复杂度的话就是O(nlogn),具体的介绍很多个链接都有,具体看下面给出的两个链接,它们对我起到非常大的帮助。

http://blog.csdn.net/famousdt/article/details/7064866

http://www.cnblogs.com/pony1993/archive/2012/07/17/2594544.html

写的时候尤其是递归询问区间的时候很容易出现off-by-one error,我在纸上比划了很久才搞清楚的。有点微弱呀- -0下面是代码。800多ms,是函数式线段数的时间的一半吧

  1. #pragma warning(disable:4996)
  2. #include<iostream>
  3. #include<cstring>
  4. #include<string>
  5. #include<cstdio>
  6. #include<algorithm>
  7. #include<vector>
  8. #include<cmath>
  9. #define maxn 100000
  10. using namespace std;
  11.  
  12. int tree[22][maxn + 50];
  13. int toleft[22][maxn + 50];
  14. int as[maxn + 50];
  15. int n, q;
  16.  
  17. void build(int l, int r, int dep)
  18. {
  19. if (l == r) return;
  20. int mid = (l + r) >> 1;
  21. int same = mid - l + 1;
  22. for (int i = l; i <= r; i++){
  23. if (tree[dep][i] < as[mid]){
  24. same--;
  25. }
  26. }
  27. int ls = l;
  28. int rs = mid + 1;
  29. for (int i = l; i <= r; i++){
  30. if (tree[dep][i] < as[mid]) tree[dep + 1][ls++] = tree[dep][i];
  31. else if (tree[dep][i] == as[mid] && same) tree[dep + 1][ls++] = tree[dep][i], same--;
  32. else tree[dep + 1][rs++] = tree[dep][i];
  33. toleft[dep][i] = toleft[dep][l - 1] + ls - l;
  34. }
  35. build(l, mid, dep + 1);
  36. build(mid + 1, r, dep + 1);
  37. }
  38.  
  39. int query(int left, int right, int k, int L, int R, int dep)
  40. {
  41. if (left == right) return tree[dep][left];
  42. int mid = (L + R) >> 1;
  43. int x = toleft[dep][left - 1] - toleft[dep][L - 1];
  44. int y = toleft[dep][right] - toleft[dep][L - 1];
  45. int rx = left - 1 - L + 1 - x;
  46. int ry = right - L + 1 - y;
  47. int cnt = y - x;
  48. if (cnt >= k) return query(L + x, L + y - 1, k, L, mid, dep + 1);
  49. // 注意off-by-one error.
  50. else return query(mid + 1 + rx,mid + 1 + ry - 1, k - cnt, mid + 1, R, dep + 1);
  51. }
  52.  
  53. int main()
  54. {
  55. while (cin >> n >> q)
  56. {
  57. for (int i = 1; i <= n; i++){
  58. scanf("%d", as + i);
  59. tree[0][i] = as[i];
  60. }
  61. sort(as + 1, as + n + 1);
  62. build(1, n, 0);
  63. int li, ri, ki;
  64. for (int i = 0; i < q; i++){
  65. scanf("%d%d%d", &li, &ri, &ki);
  66. printf("%d\n", query(li, ri, ki, 1, n, 0));
  67. }
  68. }
  69. return 0;
  70. }

POJ2104 k-th number 划分树的更多相关文章

  1. 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 ...

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

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

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

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

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

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

  5. hdu 2665 Kth number(划分树模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2665 [ poj 2104 2761 ]  改变一下输入就可以过 http://poj.org/problem? ...

  6. HDU 2665 Kth number(划分树)

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

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

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

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

随机推荐

  1. hdu 六度分离 floyd

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1869 题意分析:比较简单的最短路算法,最后只需判断最远两点距离是否大于7即可. /*六度分离 Time ...

  2. Connected_Component Labelling(联通区域标记算法) C++实现

    // Connected-Component Labelling.cpp : 定义控制台应用程序的入口点.//如有是使用,请务必注明引用出处网站:http://www.cnblogs.com/Amat ...

  3. BCB6中SCALERICHVIEW加入GIF动画

    记载下,花了不少时间. 1.  项目导入文件GIFImage.pas 来源:http://melander.dk/delphi/gifimage/ 2.  项目导入文件RVGifAnimate.pas ...

  4. 【Newtonsoft.Json】Window Phone Json解析开发包

    WP从服务器.API交换数据一般都是用JSON格式字符串. 下面介绍用Newtonsoft.Json来处理JSON. 准备 1.到 http://json.codeplex.com/ 下载Newton ...

  5. js 字符串“123”,变成整数123,不用parseInt 函数

    var s = "123"; console.log(s.charAt(0)*100+s.charAt(1)*10+s.charAt(2)*1);

  6. Allegro设置十字大光标

    使用大十字光标,在摆放元器件时,容易对齐.在allegro中,可以通过设置实现大十字光标,其具体方法如下: 1.选择Setup->User Perferences,即可出现如下图所示界面: 2. ...

  7. Vue.js 2.0版

    Vue.js 2.0版升级,更改了好多方法或指令 new Vue({ el:'#demo', data:{ msg:"vue2.0" } }) v-model lazy numbe ...

  8. Git命令收集【不断更新中】

    git stash 可以用来保存暂时不想提交但又被修改过的文件. git stash pop 用来取出被保存在stash栈中的修改过的所有文件. git stash show 查询哪些文件被存放在了s ...

  9. Scrapy源码学习(二)

    上次说到scrapy_home/scrapy/commands包下每个模块对应了scrapy命令行中的一个命令,他们都继承自command.py模块中ScrapyCommand这个类,这次就来简单看一 ...

  10. js Table冻结表头示例代码

    Table冻结表头的js实现代码. Table冻结表头: <script type="text/javascript"> //冻结table的表头  function  ...