求区间第k小
题目链接:https://www.luogu.org/problem/P3834
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define met(a, x) memset(a,x,sizeof(a)) #define inf 0x3f3f3f3f #define Rint register int using namespace std; const ll mod = 1e9 + 7; const int N = 2e5 + 10; const int M = 3e6 + 10; int a[N], b[N], c[N], cnt; int sum[N << 5], L[N << 5], R[N << 5]; inline int build(int l, int r) { int rt = ++cnt; sum[rt] = 0; if (l < r) { int mid = (l + r) / 2; L[rt] = build(l, mid); R[rt] = build(mid + 1, r); } return rt; } inline int update(int pre, int l, int r, int x) { int rt = ++cnt; L[rt] = L[pre], R[rt] = R[pre], sum[rt] = sum[pre] + 1; if (l < r) { int mid = (l + r) / 2; if (x <= mid)L[rt] = update(L[pre], l, mid, x); else R[rt] = update(R[pre], mid + 1, r, x); } return rt; } inline int query(int u, int v, int l, int r, int k) { if (l >= r)return l; int x = sum[L[v]] - sum[L[u]]; int mid = (l + r) / 2; if (x >= k)return query(L[u], L[v], l, mid, k); else return query(R[u], R[v], mid + 1, r, k - x); } int main() { // freopen("in","r",stdin); // freopen("out","w",stdout); ios::sync_with_stdio(false); cin.tie(0); int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> a[i]; b[i] = a[i]; } sort(b + 1, b + 1 + n); int len = unique(b + 1, b + 1 + n) - (b + 1); c[0] = build(1, len); for (int i = 1; i <= n; i++) { int t = lower_bound(b + 1, b + 1 + len, a[i]) - b; c[i] = update(c[i - 1], 1, len, t); } while (m--) { int x, y, z; cin >> x >> y >> z; int t = query(c[x - 1], c[y], 1, len, z); cout << b[t] << endl; } return 0; }
动态主席树,求区间第k小