K-th Number POJ - 2104

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.
 
 
题意:求区间第k大
题解:主席树的板子
  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<sstream>
  6. #include<cmath>
  7. #include<stack>
  8. #include<cstdlib>
  9. #include <vector>
  10. #include<queue>
  11. using namespace std;
  12.  
  13. #define ll long long
  14. #define llu unsigned long long
  15. #define INF 0x3f3f3f3f
  16. #define PI acos(-1.0)
  17. const int maxn = 1e5+;
  18. const int mod = 1e9+;
  19.  
  20. int n,q,m,tot;
  21. int a[maxn],t[maxn],T[maxn],lson[maxn*],rson[maxn*],c[maxn*];
  22.  
  23. void Init_hash()
  24. {
  25. for(int i=;i<=n;i++)
  26. t[i] = a[i];
  27. sort(t+,t++n);
  28. m = unique(t+,t++n)-t-;
  29. }
  30.  
  31. int build(int l,int r)
  32. {
  33. int root = tot++;
  34. c[root] = ;
  35. if (l != r)
  36. {
  37. int mid = (l+r) >> ;
  38. lson[root] = build(l,mid);
  39. rson[root] = build(mid+,r);
  40. }
  41. return root;
  42. }
  43. int Hash(int x)
  44. {
  45. return lower_bound(t+,t++m,x)-t;
  46. }
  47. int update(int root,int pos,int val)
  48. {
  49. int newroot = tot ++,tmp = newroot;
  50. c[newroot] = c[root] + val;
  51. int l = ,r = m;
  52. while(l <r)
  53. {
  54. int mid = (l+r)>>;
  55. if(pos <= mid)
  56. {
  57. lson[newroot] = tot++;
  58. rson[newroot] = rson[root];
  59. newroot = lson[newroot];
  60. root = lson[root];
  61. r = mid;
  62. }
  63. else
  64. {
  65. rson[newroot] = tot ++;
  66. lson[newroot] = lson[root];
  67. newroot = rson[newroot];
  68. root = rson[root];
  69. l = mid + ;
  70. }
  71. c[newroot] = c[root] + val;
  72. }
  73. return tmp;
  74.  
  75. }
  76. int query(int left_root,int right_root,int k)
  77. {
  78. int l = ,r = m;
  79. while(l < r)
  80. {
  81. int mid = (l+r) >> ;
  82. if(c[lson[left_root]] - c[lson[right_root]] >= k)
  83. {
  84. r = mid;
  85. left_root = lson[left_root];
  86. right_root = lson[right_root];
  87. }
  88. else
  89. {
  90. l = mid + ;
  91. k -= c[lson[left_root]] - c[lson[right_root]];
  92. left_root = rson[left_root];
  93. right_root = rson[right_root];
  94. }
  95. }
  96. return l;
  97. }
  98. int main()
  99. {
  100. scanf("%d%d",&n,&q);
  101. tot = ;
  102. for(int i=;i<=n;i++)
  103. scanf("%d",&a[i]);
  104. Init_hash();
  105. T[n+] = build(,m);
  106. for(int i=n;i;i--)
  107. {
  108. int pos = Hash(a[i]);
  109. T[i] = update(T[i+],pos,);
  110. }
  111. while(q--)
  112. {
  113. int l,r,k;
  114. scanf("%d%d%d",&l,&r,&k);
  115. printf("%d\n",t[query(T[l],T[r+],k)]);
  116. }
  117. }
  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<stack>
  7. #include<cstdlib>
  8. #include<queue>
  9. #include<set>
  10. #include<string.h>
  11. #include<vector>
  12. #include<deque>
  13. #include<map>
  14. using namespace std;
  15. #define INF 0x3f3f3f3f3f3f3f3f
  16. #define inf 0x3f3f3f3f
  17. #define eps 1e-4
  18. #define bug printf("*********\n")
  19. #define debug(x) cout<<#x"=["<<x<<"]" <<endl
  20. typedef long long LL;
  21. typedef long long ll;
  22. const int maxn = 2e5 + ;
  23. const int mod = ;
  24. int n,m,a[maxn],root[maxn],cnt;
  25. vector<int>v;
  26. struct node{
  27. int l,r,sum;
  28. }T[maxn * ];
  29. int getid(int x) {
  30. return lower_bound(v.begin(),v.end(),x) - v.begin() + ;
  31. }
  32. void update(int l,int r,int &x,int y,int pos) {
  33. T[++cnt] = T[y],T[cnt].sum ++,x = cnt;
  34. if(l == r) return;
  35. int mid = (l + r) / ;
  36. if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos);
  37. else update(mid + ,r,T[x].r,T[y].r,pos);
  38. }
  39. int query(int l,int r,int x,int y,int k) {
  40. if(l == r) return l;
  41. int mid = (l + r) / ;
  42. int sum = T[T[y].l].sum - T[T[x].l].sum;
  43. if(sum >= k) return query(l,mid,T[x].l,T[y].l,k);
  44. else return query(mid + ,r,T[x].r,T[y].r,k - sum);
  45. }
  46. void init() {
  47. cnt = ;
  48. memset(root,,sizeof root);
  49. }
  50. int main()
  51. {
  52. init();
  53. scanf("%d %d",&n,&m);
  54. for (int i = ; i <= n; ++i) {
  55. scanf("%d",&a[i]);
  56. v.push_back(a[i]);
  57. }
  58. sort(v.begin(),v.end());
  59. v.erase(unique(v.begin(),v.end()),v.end());
  60. for (int i = ; i <= n; ++i)
  61. update(,n,root[i],root[i - ],getid(a[i]));
  62. for (int i = ; i <= m; ++i) {
  63. int x,y,k;
  64. scanf("%d %d %d",&x, &y, &k);
  65. printf("%d\n",v[query(,n,root[x - ],root[y],k) - ]);
  66. }
  67. }
  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<stack>
  7. #include<cstdlib>
  8. #include<queue>
  9. #include<set>
  10. #include<string.h>
  11. #include<vector>
  12. #include<deque>
  13. #include<map>
  14. using namespace std;
  15. #define INF 0x3f3f3f3f3f3f3f3f
  16. #define inf 0x3f3f3f3f
  17. #define eps 1e-4
  18. #define bug printf("*********\n")
  19. #define debug(x) cout<<#x"=["<<x<<"]" <<endl
  20. typedef long long LL;
  21. typedef long long ll;
  22. const int maxn = 2e5 + ;
  23. const int mod = ;
  24. int n,m,a[maxn],root[maxn],cnt;
  25. /*
  26. root:代表每个历史版本线段树的根节点位置
  27. cnt:用作开辟新的树节点
  28. */
  29. vector<int>v;
  30. struct node{
  31. int l,r,sum;
  32. }T[maxn * ]; //线段树区间统计,sum代表在这个区间数的个数
  33. int getid(int x) { //获取离散数组后的下标
  34. return lower_bound(v.begin(),v.end(),x) - v.begin() + ;
  35. }
  36. /*
  37. update函数:
  38. y代表前一棵树的节点位置,x是后面的节点位置
  39. */
  40. void update(int l,int r,int &x,int y,int pos) {
  41. //&x 引用节点指针扩展新节点
  42. T[++cnt] = T[y],T[cnt].sum ++,x = cnt; //新开节点,将需要修改的树节点复制到新开辟节点,改变自己的sum
  43. if(l == r) return;
  44. int mid = (l + r) / ;
  45. if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos); //节点左边
  46. else update(mid + ,r,T[x].r,T[y].r,pos); //节点右边
  47. }
  48. int query(int l,int r,int x,int y,int k) {
  49. if(l == r) return l;
  50. int mid = (l + r) / ;
  51. int sum = T[T[y].l].sum - T[T[x].l].sum; //两颗线段树sum做差
  52. if(sum >= k) return query(l,mid,T[x].l,T[y].l,k); //如果当前的结点个数sum比k要大的话,说明第k大的结点在左子树当中,就去遍历左子树
  53. else return query(mid + ,r,T[x].r,T[y].r,k - sum); //如果当前的结点个数sum比k要小的话,说明第k大的结点在右子树当中,而左子树的结点个数是sum个,那就去找右子树中的第k-sum的数
  54. }
  55. void init() {
  56. cnt = ;
  57. memset(root,,sizeof root);
  58. }
  59. int main()
  60. {
  61. init();
  62. scanf("%d %d",&n,&m);
  63. for (int i = ; i <= n; ++i) {
  64. scanf("%d",&a[i]);
  65. v.push_back(a[i]); //离散化数组
  66. }
  67. sort(v.begin(),v.end()); //离散化数组
  68. v.erase(unique(v.begin(),v.end()),v.end()); //离散化数组
  69.  
  70. for (int i = ; i <= n; ++i) {
  71. update(, n, root[i], root[i - ], getid(a[i]));
  72. }
  73. for (int i = ; i <= m; ++i) {
  74. int x,y,k;
  75. scanf("%d %d %d",&x, &y, &k);
  76. printf("%d\n",v[query(,n,root[x - ],root[y],k) - ]);
  77. }
  78. }

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

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

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

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

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

  3. K-th Number POJ - 2104 划分树

    K-th Number You are working for Macrohard company in data structures department. After failing your ...

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

  5. AC日记——K-th Number poj 2104

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

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

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

  7. POJ 2104&HDU 2665 Kth number(主席树入门+离散化)

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

  8. poj 2104 K-th Number 主席树+超级详细解释

    poj 2104 K-th Number 主席树+超级详细解释 传送门:K-th Number 题目大意:给出一段数列,让你求[L,R]区间内第几大的数字! 在这里先介绍一下主席树! 如果想了解什么是 ...

  9. poj 2104 K-th Number(主席树,详细有用)

    poj 2104 K-th Number(主席树) 主席树就是持久化的线段树,添加的时候,每更新了一个节点的线段树都被保存下来了. 查询区间[L,R]操作的时候,只需要用第R棵树减去第L-1棵树就是区 ...

随机推荐

  1. form中onsubmit的使用

    form 中的onsubmit在点submit按钮时被触发,如果return false;则结果不会被提交到action中去(也就是提交动作不会发生),如果不返回或者返回true,则执行提交动作.(& ...

  2. web 单例 多例

    单例多例需要搞明白两个问题:1. 什么是单例多例:2. 如何产生单例多例:3. 为什么要用单例多例4. 什么时候用单例,什么时候用多例:1. 什么是单例多例:所谓单例就是所有的请求都用一个对象来处理, ...

  3. jQuery学习笔记(四)

    动画效果 显示和隐藏效果 无动画效果 显示:show() 隐藏:hide() <!DOCTYPE html> <html lang="en"> <he ...

  4. 少写代码帮你模块化方法 & 运动框架 & 简化轮播图

    模块化就是通过每一个js里封装一个方法:用exports将他输出, 在下一个js用require的方法加载js时就会将方法输出.然后在主页面引入require.js; 模块化基本写法: define( ...

  5. spring mvc <mvc;resources>

    spring mvc 的<mvc;resources mapping="***" location="***">标签是在spring3.0.4出现的 ...

  6. MAC MAMP install yaf

    Yaf doesn't support PHP 5.6! You may see this: Warning: PHP Startup: yaf: Unable to initialize modul ...

  7. mif文件生成方法

    mif文件就是存储器初始化文件,即memory initialization file,用来配置RAM或ROM中的数据.常见生成方法: Quartus自带的mif编辑器生成 mif软件生成 高级编程语 ...

  8. ubuntu 自动启动程序

    首先打开终端ctrl + alt + t sudo  -i 输入密码:ubuntu chmod 777 /etc/rc.local 打开  vi   /etc/rc.local 按  i  键进入输入 ...

  9. php使用GD库实现图片水印和缩略图——给图片添加图片水印

    今天呢,就来学习一下在php中使用PD库来实现对图片水印的文字水印方法,不需要PS哦! 首先,准备素材 (1)准备一张图片 (2)准备一张水印(最好是透明的,即背景是白色底) (3)准备一中字体(在电 ...

  10. [Git] Create a new repository on the command line

    echo "# xxx" >> README.md git init git add README.md git commit -m "first commi ...