求区间第k小的数
#include <bits/stdc++.h>#define int long longusing namespace std;const int N = 2e5+5;int n, q, m, id;//rt[u]表示存储节点u所在线段树的根节点编号int a[N], b[N], root[N];//L[u],R[u]分别表示节点u的左/右儿子编号//s[u]表示节点u的权值(该节点代表的区间中有多少个数)int s[N<<5], L[N<<5], R[N<<5];int build(int l, int r) {int rt = ++id;s[rt] = 0;int mid = l+r>>1;if (l < r) {L[rt] = build(l, mid);R[rt] = build(mid+1, r);}return rt;}int update(int pre, int l, int r, int x) {int rt = ++id;int mid = l+r>>1;L[rt] = L[pre], R[rt] = R[pre];s[rt] = s[pre]+1;if (l != r) {if (x <= mid) {L[rt] = update(L[pre], l, mid, x);} else {R[rt] = update(R[pre], mid+1, r, x);}}return rt;}int query(int u, int v, int l, int r, int k) {if (l == r) {return l;}//求出区间[l,r]中的数有多少个int x = s[L[v]]-s[L[u]];int mid = l+r>>1;//二分查找if (x >= k) {return query(L[u], L[v], l, mid, k);} else {return query(R[u], R[v], mid+1, r, k-x);}}signed main() {ios::sync_with_stdio(false);cin.tie(0);cin >> n >> q;for (int i = 1; i <= n; i++) {cin >> a[i];b[i] = a[i];}sort(b+1, b+n+1);//离散化m = unique(b+1, b+n+1)-b-1;//建立一颗有m个节点的空树root[0] = build(1, m);for (int i = 1; i <= n; i++) {//找到离散化之后的数组中a[i]第一次出现的位置pint p = lower_bound(b+1, b+m+1, a[i])-b;/*复制上一颗线段树的根节点新建一颗线段树且权值加1,对于一个儿子的值域区间,如果权值有变化,那么新建一个节点,否则,连到原来的那个节点上*/root[i] = update(root[i-1], 1, m, p);}while (q--) {int x, y, z;cin >> x >> y >> z;//前缀和思想int p = query(root[x-1], root[y], 1, m, z);cout << b[p] << "\n";}return 0;}
