1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| #include<iostream> #include<cstring> #include<cstdlib> #include<cmath> #include<cstdio> #include<algorithm> #include<set> #include<vector> using namespace std; const int N = 2e5 + 5, M = 100000; int n, m; int a[N]; struct Node{ int l, r; int cnt; }tr[(int)5e6]; int root[N], idx; vector<int>nums; int find(int x) { return lower_bound(nums.begin(), nums.end(), x) - nums.begin(); } int build(int l, int r) { int p = ++ idx; if(l == r) return p; int mid = l + r >> 1; tr[p].l = build(l, mid), tr[p].r = build(mid + 1, r); return p; } int insert(int p, int l, int r, int x) { int q = ++ idx; tr[q] = tr[p]; if (l == r) { tr[q].cnt ++ ; return q; } int mid = l + r >> 1; if (x <= mid) tr[q].l = insert(tr[p].l, l, mid, x); else tr[q].r = insert(tr[p].r, mid + 1, r, x); tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt; return q; } int query(int q, int p, int l, int r, int k) { if (l == r) return r; int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt; int mid = l + r >> 1; if (k <= cnt) return query(tr[q].l, tr[p].l, l, mid, k); else return query(tr[q].r, tr[p].r, mid + 1, r, k - cnt); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i ++ ) { scanf("%d", &a[i]); nums.push_back(a[i]); } sort(nums.begin(), nums.end()); nums.erase(unique(nums.begin(), nums.end()), nums.end()); root[0] = build(0, nums.size() - 1); for (int i = 1; i <= n; i ++ ) root[i] = insert(root[i - 1], 0, nums.size() - 1, find(a[i]));
while(m --) { int l, r, k; scanf("%d%d%d", &l, &r, &k); printf("%d\n", nums[query(root[r], root[l - 1], 0, nums.size() - 1, k)]); } return 0; }
|