P3834 【模板】可持久化线段树 1(主席树)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2e5+5; 4 int n, q, m, cnt = 0; 5 int a[maxn], b[maxn], T[maxn]; 6 int sum[maxn<<5], L[maxn<<5], R[maxn<<5]; 7 inline int build(int l, int r) { 8 int rt = ++cnt; 9 sum[rt] = 0; 10 if (l < r) { 11 int mid = (l+r)/2; 12 L[rt] = build(l, mid); 13 R[rt] = build(mid+1, r); 14 } 15 return rt; 16 } 17 inline int update(int pre, int l, int r, int x) { 18 int rt = ++cnt; 19 L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre]+1; 20 if (l < r) { 21 int mid = (l+r)/2; 22 if (x <= mid) L[rt] = update(L[pre], l, mid, x); 23 else R[rt] = update(R[pre], mid+1, r, x); 24 } 25 return rt; 26 } 27 inline int query(int u, int v, int l, int r, int k) { 28 if (l >= r) return l; 29 int x = sum[L[v]] - sum[L[u]]; 30 int mid = (l+r)/2; 31 if (x >= k) return query(L[u], L[v], l, mid, k); 32 else return query(R[u], R[v], mid+1, r, k-x); 33 } 34 int main() { 35 scanf("%d%d",&n,&q); 36 for (int i = 1; i <= n; ++i) { 37 scanf("%d",&a[i]); 38 b[i] = a[i]; 39 } 40 sort(b+1,b+1+n); 41 m = unique(b+1,b+1+n)-b-1; 42 T[0] = build(1,m); 43 for (int i = 1; i <= n; ++i) { 44 int t = lower_bound(b+1,b+1+m,a[i])-b; 45 T[i] = update(T[i-1], 1, m, t); 46 } 47 while (q--) { 48 int l, r, k; 49 scanf("%d%d%d",&l,&r,&k); 50 int t = query(T[l-1], T[r], 1, m, k); 51 printf("%d\n",b[t]); 52 } 53 return 0; 54 }