当前位置:   article > 正文

可持久化线段树_leetcode 可持久化线段树

leetcode 可持久化线段树

 可持久化线段树相比可持久化Trie来说要简单一点,因为线段树的结构固定,无论如何添加信息结构都不会改变,时间复杂度为O(nlogn)

可持久化线段树维护的是值域,在数值上建立线段树,并维护每个数值区间一共有多少数

例题:第k小数255. 第K小数 - AcWing题库 

给定长度为 N 的整数序列 A,下标为 1∼N。

现在要执行 M 次操作,其中第 i 次操作为给出三个整数 li , ri , ki,求 A[ li ],A[ li+1 ],…,A[ ri ] (即 A 的下标区间 [ li,ri ])中第 ki 小的数是多少。

输入格式

第一行包含两个整数 N 和 M。

第二行包含 N 个整数,表示整数序列 A。

接下来 M 行,每行包含三个整数 li ,ri ,ki ,用以描述第 i 次操作。

输出格式

对于每次操作输出一个结果,表示在该次操作中,第 k 小的数的数值。

每个结果占一行。

数据范围

N ≤ 105,M ≤ 104,|A[i]| ≤ 109

输入样例:

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

输出样例: 

  1. 5
  2. 6
  3. 3

 解题思路:

先来想如何求整体的第k小数,只需要递归即可,现在加入了区间限制,如果求的是1~R的第k小数,则只需要找刚好加完R个数的线段树版本,如果求的是1~L的第k小数,则只需要找刚好加完L个数的线段树版本,如果求的是L~R的第k小数,则可以用前缀和思想,用R的版本减去L的版本

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<vector>
  6. using namespace std;
  7. const int N=100010,M=10010;
  8. int n,m;
  9. int a[N];
  10. vector<int> nums;
  11. struct node
  12. {
  13. int l,r;
  14. int cnt;
  15. }tr[N * 4 + N * 17];
  16. int root[N],idx;
  17. int find(int x)
  18. {
  19. return lower_bound(nums.begin(),nums.end(),x) - nums.begin();
  20. }
  21. int build(int l,int r)
  22. {
  23. int p = ++ idx;
  24. if(l == r)
  25. return p;
  26. int mid= l + r >> 1;
  27. tr[p].l=build(l,mid),tr[p].r=build(mid + 1,r);
  28. return p;
  29. }
  30. int insert(int p,int l,int r,int x)
  31. {
  32. int q= ++ idx;
  33. tr[q]=tr[p];
  34. if(l == r)
  35. {
  36. tr[q].cnt++;
  37. return q;
  38. }
  39. int mid = l + r >> 1;
  40. if(x <= mid)
  41. tr[q].l = insert(tr[p].l,l,mid,x);
  42. else
  43. tr[q].r = insert(tr[p].r,mid + 1,r,x);
  44. tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt;
  45. return q;
  46. }
  47. int query(int q,int p,int l,int r,int k)
  48. {
  49. if(l == r)
  50. return r;
  51. int cnt=tr[tr[q].l].cnt - tr[tr[p].l].cnt;
  52. int mid = l + r >> 1;
  53. if(k<=cnt)
  54. return query(tr[q].l,tr[p].l,l,mid,k);
  55. else
  56. return query(tr[q].r,tr[p].r,mid + 1,r,k - cnt);
  57. }
  58. int main()
  59. {
  60. scanf("%d%d", &n, &m);
  61. for(int i = 1; i <= n; i ++)
  62. {
  63. scanf("%d", &a[i]);
  64. nums.push_back(a[i]);
  65. }
  66. sort(nums.begin(),nums.end());
  67. nums.erase(unique(nums.begin(),nums.end()),nums.end());
  68. root[0]=build(0,nums.size()-1);
  69. for(int i = 1; i <= n; i ++)
  70. {
  71. root[i] = insert(root[i - 1],0,nums.size() - 1,find(a[i]));
  72. }
  73. while(m--)
  74. {
  75. int l,r,k;
  76. scanf("%d%d%d",&l,&r,&k);
  77. printf("%d\n",nums[query(root[r],root[l - 1],0,nums.size() - 1,k)]);
  78. }
  79. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号