当前位置:   article > 正文

[卡空间][可持久化线段树]Couriers LibreOJ2432_线段树 出现次数大于等于k

线段树 出现次数大于等于k

给定长度为 n 的正整数序列。
有 m 组查询,每次查询区间 [a,b] 中出现次数严格大于一半的数。
即:出现次数大于等于(b-a+1)/2+1的数。

Input

第一行两个整数 n,m (1 ≤ n,m ≤ 500000),表示序列的长度和询问的个数。

接下来一行 n 个整数 p1, p2, …, pn (1 ≤ pi ≤ n),表示该序列。

接下来 m 行,每行两个整数 a,b (1 ≤ a ≤ b ≤ n),表示查询从第 a 个数到第 b 个数之间(包括两个数本身)出现次数严格大于一半的数,如果没有则输出 0.

Output

输出 m 行,对每个询问,输出一行一个整数,表示出现次数超过一半的数,如果没有则输出 0.

Sample Input

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

Sample Output

1
0
3
0
4

题意: 给出一个长度为n的序列以及m次询问,每次询问区间内出现次数严格大于区间长度一半的数。

分析: 比较明显的主席树题目,和主席树模板一样维护区间内权值出现次数,在查询的时候如果左区间个数大于等于目标次数就递归进左区间,如果右区间个数大于等于目标次数就递归进右区间,如果这两种情况都无法进入就直接返回0,表示无法找到符合题意的数。

这道题目这样就可以解决了,但是由于空间卡的实在是太死了,导致疯狂MLE

最后加了个离散化水过去了,理论上数据再严格点加离散化也不应该过的......

具体代码如下: 

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <string>
  7. #include <vector>
  8. using namespace std;
  9. const int N = 5e5+5;
  10. struct node{
  11. int l, r, num;
  12. }tr[24*N];
  13. int n, m, cnt, a[N], rt[N];
  14. vector<int> alls;
  15. int find(int x){
  16. return lower_bound(alls.begin(), alls.end(), x)-alls.begin()+1;
  17. }
  18. int build(int l, int r){
  19. int id = ++cnt;
  20. if(l == r) return id;
  21. int mid = l+r>>1;
  22. tr[id].l = build(l, mid);
  23. tr[id].r = build(mid+1, r);
  24. return id;
  25. }
  26. int insert(int L, int l, int r, int x){
  27. int id = ++cnt;
  28. tr[id] = tr[L];
  29. tr[id].num++;
  30. if(l == r) return id;
  31. int mid = l+r>>1;
  32. if(x <= mid) tr[id].l = insert(tr[L].l, l, mid, x);
  33. else tr[id].r = insert(tr[L].r, mid+1, r, x);
  34. return id;
  35. }
  36. //寻找出现次数大于等于k的数
  37. int query(int L, int R, int l, int r, int k){
  38. if(l == r) return l;
  39. int mid = l+r>>1;
  40. int num_l = tr[tr[R].l].num-tr[tr[L].l].num;
  41. int num_r = tr[tr[R].r].num-tr[tr[L].r].num;
  42. if(num_l >= k) return query(tr[L].l, tr[R].l, l, mid, k);
  43. if(num_r >= k) return query(tr[L].r, tr[R].r, mid+1, r, k);
  44. return 0;
  45. }
  46. signed main()
  47. {
  48. cin >> n >> m;
  49. for(int i = 1; i <= n; i++){
  50. scanf("%d", &a[i]);
  51. alls.push_back(a[i]);
  52. }
  53. sort(alls.begin(), alls.end());
  54. alls.erase(unique(alls.begin(), alls.end()), alls.end());
  55. rt[0] = build(1, alls.size());
  56. for(int i = 1; i <= n; i++)
  57. rt[i] = insert(rt[i-1], 1, alls.size(), find(a[i]));
  58. for(int i = 1; i <= m; i++){
  59. int l, r, ans;
  60. scanf("%d%d", &l, &r);
  61. ans = query(rt[l-1], rt[r], 1, alls.size(), (r-l+1)/2+1);
  62. if(!ans) puts("0");
  63. else printf("%d\n", alls[ans-1]);
  64. }
  65. return 0;
  66. }

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

闽ICP备14008679号