求区间第k小的数

    1. #include <bits/stdc++.h>
    2. #define int long long
    3. using namespace std;
    4. const int N = 2e5+5;
    5. int n, q, m, id;
    6. //rt[u]表示存储节点u所在线段树的根节点编号
    7. int a[N], b[N], root[N];
    8. //L[u],R[u]分别表示节点u的左/右儿子编号
    9. //s[u]表示节点u的权值(该节点代表的区间中有多少个数)
    10. int s[N<<5], L[N<<5], R[N<<5];
    11. int build(int l, int r) {
    12. int rt = ++id;
    13. s[rt] = 0;
    14. int mid = l+r>>1;
    15. if (l < r) {
    16. L[rt] = build(l, mid);
    17. R[rt] = build(mid+1, r);
    18. }
    19. return rt;
    20. }
    21. int update(int pre, int l, int r, int x) {
    22. int rt = ++id;
    23. int mid = l+r>>1;
    24. L[rt] = L[pre], R[rt] = R[pre];
    25. s[rt] = s[pre]+1;
    26. if (l != r) {
    27. if (x <= mid) {
    28. L[rt] = update(L[pre], l, mid, x);
    29. } else {
    30. R[rt] = update(R[pre], mid+1, r, x);
    31. }
    32. }
    33. return rt;
    34. }
    35. int query(int u, int v, int l, int r, int k) {
    36. if (l == r) {
    37. return l;
    38. }
    39. //求出区间[l,r]中的数有多少个
    40. int x = s[L[v]]-s[L[u]];
    41. int mid = l+r>>1;
    42. //二分查找
    43. if (x >= k) {
    44. return query(L[u], L[v], l, mid, k);
    45. } else {
    46. return query(R[u], R[v], mid+1, r, k-x);
    47. }
    48. }
    49. signed main() {
    50. ios::sync_with_stdio(false);
    51. cin.tie(0);
    52. cin >> n >> q;
    53. for (int i = 1; i <= n; i++) {
    54. cin >> a[i];
    55. b[i] = a[i];
    56. }
    57. sort(b+1, b+n+1);
    58. //离散化
    59. m = unique(b+1, b+n+1)-b-1;
    60. //建立一颗有m个节点的空树
    61. root[0] = build(1, m);
    62. for (int i = 1; i <= n; i++) {
    63. //找到离散化之后的数组中a[i]第一次出现的位置p
    64. int p = lower_bound(b+1, b+m+1, a[i])-b;
    65. /*
    66. 复制上一颗线段树的根节点新建一颗线段树且权值加1,
    67. 对于一个儿子的值域区间,如果权值有变化,
    68. 那么新建一个节点,否则,连到原来的那个节点上
    69. */
    70. root[i] = update(root[i-1], 1, m, p);
    71. }
    72. while (q--) {
    73. int x, y, z;
    74. cin >> x >> y >> z;
    75. //前缀和思想
    76. int p = query(root[x-1], root[y], 1, m, z);
    77. cout << b[p] << "\n";
    78. }
    79. return 0;
    80. }