poj2104

题意

给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数。

分析

划分树模板,O(mlogn)。

  1. 建树。根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右子树(在子区间内数与数的相对位置保持不变),递归向下分割。
  2. 查询。toleft[p][i] 表示第 p 层前 i 个数中有多少个整数分入下一层。查询最重要的是确定新的查询区间,若递归查询左区间,则新的子区间的左边一定是上一层区间 [L, l - 1] 里的 toleft[dep][l-1] - toleft[dep][L-1] 个整数,那么 newl = L + toleft[dep][l-1] - toleft[dep][L-1],[l, r] 区间内有cnt = toleft[dep][r] - toleft[dep][l - 1] 个数,所以 newr = newl + cnt - 1;查询右区间则要先确定 newr 的值,[r+1, R] 中有 c = toleft[dep][R] - toleft[dep][r] 个整数位于左子区间的右方,所以查询区间 r 要向右移 c 个数,newr = r + c,newl = newr - (r - l - cnt)。

code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<vector>
  5. using namespace std;
  6. typedef long long ll;
  7. const int INF = 1e9;
  8. const int MAXN = 1e5 + 5;
  9. const int LOG_N = 30;
  10. // tree[dep][i] 第dep层第i个位置的数值
  11. int tree[LOG_N][MAXN];
  12. int sorted[MAXN];
  13. // toleft[p][i] 第p层前i个数中有多少个整数分入下一层
  14. int toleft[LOG_N][MAXN];
  15. void build(int l, int r, int dep)
  16. {
  17. if(l == r) return;
  18. int mid = (l + r) / 2;
  19. int same = mid - l + 1; // 和中点数相同的数的个数
  20. for(int i = l; i <= r; i++)
  21. if(tree[dep][i] < sorted[mid]) same--;
  22. int lpos = l, rpos = mid + 1;
  23. for(int i = l; i <= r; i++)
  24. {
  25. if(tree[dep][i] < sorted[mid])
  26. tree[dep + 1][lpos++] = tree[dep][i];
  27. else if(tree[dep][i] == sorted[mid] && same)
  28. {
  29. tree[dep + 1][lpos++] = tree[dep][i];
  30. same--;
  31. }
  32. else tree[dep + 1][rpos++] = tree[dep][i];
  33. toleft[dep][i] = toleft[dep][l - 1] + lpos - l;
  34. }
  35. build(l, mid, dep + 1);
  36. build(mid + 1, r, dep + 1);
  37. }
  38. // [L,R]里查询子区间[l,r]第k小的数
  39. int query(int L, int R, int l, int r, int dep, int k)
  40. {
  41. if(l == r) return tree[dep][l];
  42. int mid = (L + R) / 2;
  43. // 有多少个查询区间内的节点会进入下一层的左子树
  44. int cnt = toleft[dep][r] - toleft[dep][l - 1];
  45. if(cnt >= k)
  46. {
  47. int newl = L + toleft[dep][l - 1] - toleft[dep][L - 1];
  48. int newr = newl + cnt - 1;
  49. return query(L, mid, newl, newr, dep + 1, k);
  50. }
  51. else
  52. {
  53. int newr = r + toleft[dep][R] - toleft[dep][r];
  54. int newl = newr - (r - l - cnt);
  55. return query(mid + 1, R, newl, newr, dep + 1, k - cnt);
  56. }
  57. }
  58. int main()
  59. {
  60. int n, m;
  61. while(~scanf("%d%d", &n, &m))
  62. {
  63. for(int i = 1; i <= n; i++)
  64. {
  65. scanf("%d", &sorted[i]);
  66. tree[0][i] = sorted[i];
  67. }
  68. sort(sorted + 1, sorted + n + 1);
  69. build(1, n, 0);
  70. while(m--)
  71. {
  72. int l, r, k;
  73. scanf("%d%d%d", &l, &r, &k);
  74. printf("%d\n", query(1, n, l, r, 0, k));
  75. }
  76. }
  77. return 0;
  78. }

poj2104(划分树模板)的更多相关文章

  1. poj2104(划分树模板)

    poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...

  2. hdu2665 && poj2104划分树

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

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

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

  4. HDU-3743 Minimum Sum,划分树模板

    Minimum Sum 被这个题坑了一下午,原来只需找一个最中间的数即可,我以为是平均数. 题意:找一个数使得这个数和区间内所有数的差的绝对值最小.输出最小值. 开始用线段树来了一发果断T了,然后各种 ...

  5. VIJOS P1081 野生动物园 SBT、划分树模板

    [描述] cjBBteam拥有一个很大的野生动物园.这个动物园坐落在一个狭长的山谷内,这个区域从南到北被划分成N个区域,每个区域都饲养着一头狮子.这些狮子从北到南编号为1,2,3,…,N.每头狮子都有 ...

  6. poj2104 划分树 区间K大 在线 无修改

    博主sbit....对于高级数据结构深感无力,然后这些东西在OI竟然烂大街了,不搞就整个人都不好了呢. 于是我勇猛的跳进了这个大坑 ——sbit 区间K大的裸题,在线,无修改. 可以用归并树(\(O( ...

  7. poj 2104 (划分树模板)

    Description You are working for Macrohard company in data structures department. After failing your ...

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

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

  9. poj2104 主席树模板题

    题意 给出n个数字组成的数字序列,有m组询问.每次询问包含三个数字l,r,k.对于每个询问输出序列区间[l,r]中第k大的数字. 分析 这是主席树的模板题,套板子就可以 #include <cs ...

随机推荐

  1. JDK8-十大新特性-附demo

    JDK原计划17年上半年就发版,但未成功发版.才发现JDK8的特性还没总结过,特此总结. 一.十大特性. 1.Lambda表达式 2.Stream函数式操作流元素集合 3.接口新增:默认方法与静态方法 ...

  2. java复习(5)---接口、继承、多态

    Java作为完全面向对象语言,接口.继承和多态是三个非常重要的概念. 1.继承. (1)关键字: extends (2)子类用super()调用父类构造函数,用super().方法 调用父类的成员方法 ...

  3. Python全栈之路-Day33

    1 time模块 #!/usr/bin/env python # __Author__: "wanyongzhen" # Date: 2017/4/7 import time # ...

  4. checkbox的选中、全选、返选、获取所有选中的值、所有的值、单选全部时父选中

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  5. Angular2.js——表单(上)

    表单创建一个有效.引人注目的数据输入体验.Angular表单协调一组数据绑定控件,跟踪变更.验证输入的有效性,并且显示错误信息. 接下来,主要内容有: 1.使用组件和模板构建Angular表单: 2. ...

  6. 解析PHP中常见的mongodb查询操作

    详细出处参考:http://www.jb51.net/article/38839.htm<?php// 欄位字串為$querys = array("name"=>&qu ...

  7. php函数每日学习二十个

    数学函数 1,abs() 求绝对值 2,ceil() 进一法取整 3,floor() 舍去法取整 4,fmod()对浮点数进行取余 例如fmod(5.7,1.3) 5,pow() 返回数的n次方 po ...

  8. libpng处理png图片(一)

    一:libpng库的编译 环境:windows10 + VS2013 需要下载:libpng, zlib两个库 下载地址: libpng:http://libmng.com/pub/png/libpn ...

  9. OC中常见的结构体,以及NSNumber、NSValue、NSDate的使用

    常见的结构体 NSPoint和CGPoint NSSize和CGSize NSRect 和 CGRect NSPoint和CGPoint的使用 NSPoint和CGPoint是同义的 typedef ...

  10. 记事本app TOP5(个人观点)

    1.为知笔记 为知笔记定位于高效率工作笔记,主打工作笔记的移动应用,是目前国内唯一一款"工作笔记"的云笔记类产品.除了常用的笔记功能保存的网页.灵感笔记.重要文档.照片.便签等,为 ...