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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| #include <cstdio> #include <climits> #include <algorithm> #include <new> #include <cctype> #include <cstring> #include <iostream> inline char read() { static const int IO_LEN = 1024 * 1024; static char buf[IO_LEN], *ioh, *iot; if (ioh == iot) { iot = (ioh = buf) + fread(buf, 1, IO_LEN, stdin); if (ioh == iot) return -1; } return *ioh++; } template<class T> inline void read(T &x) { static bool iosig = 0; static char ioc; for (iosig = 0, ioc = read(); !isdigit(ioc); ioc = read()) if (ioc == '-') iosig = 1; for (x = 0; isdigit(ioc); ioc = read()) x = (x << 1) + (x << 3) + (ioc ^ '0'); if (iosig) x = -x; } template<class T, size_t size> struct MemoryPool { T buf[size], *tail, *st[size]; int top; MemoryPool() : top(0), tail(buf) {} inline T *alloc() { return top ? st[--top] : tail++; } inline void recycle(T *x) { st[top++] = x;} }; const int MAXN = 3000000; struct ChairmanTree { struct Node { int l, r; Node *lc, *rc; int cnt; static inline Node *newNode(MemoryPool<Node, MAXN> &pool, const int l, const int r, Node *lc = NULL, Node *rc = NULL) { Node *tmp = pool.alloc(); tmp->l = l, tmp->r = r, tmp->lc = lc, tmp->rc = rc, tmp->cnt = (lc ? lc->cnt : 0) + (rc ? rc->cnt : 0); return tmp; } static inline Node *newNode(MemoryPool<Node, MAXN> &pool, const int l, const int r, const int cnt) { Node *tmp = pool.alloc(); tmp->l = l, tmp->r = r, tmp->cnt = cnt, tmp->lc = NULL, tmp->rc = NULL; return tmp; } inline void pushDown(MemoryPool<Node, MAXN> &pool) { if (lc && rc) return; register int mid = l + r >> 1; if (!lc) lc = newNode(pool, l, mid); if (!rc) rc = newNode(pool, mid + 1, r); } inline Node *insert(MemoryPool<Node, MAXN> &pool, const int num) { if (num < l || num > r) return this; else if (num == l && num == r) return newNode(pool, l, r, this->cnt + 1); else { register int mid = l + r >> 1; pushDown(pool); if (num <= mid) return newNode(pool, l, r, lc->insert(pool, num), rc); else return newNode(pool, l, r, lc, rc->insert(pool, num)); } } inline int rank() const { return lc ? lc->cnt : 0; } } *root[MAXN + 1]; MemoryPool<Node, MAXN> pool; int n; inline void build(const int *a, const int n) { this->n = n; root[0] = Node::newNode(pool, 0, n - 1); for (register int i = 1; i <= n; i++) root[i] = root[i - 1]->insert(pool, a[i - 1]); } inline int query(const int l, const int r, int k) { Node *L = root[l - 1], *R = root[r]; register int min = 0, max = n - 1; while (min != max) { L->pushDown(pool), R->pushDown(pool); register int mid = min + max >> 1, t = R->rank() - L->rank(); if (k <= t) L = L->lc, R = R->lc, max = mid; else k -= t, L = L->rc, R = R->rc, min = mid + 1; } return min; } } t; int n, m, a[MAXN]; int main() { read(n), read(m); for (register int i = 0; i < n; i++) read(a[i]); static int set[MAXN]; memcpy(set, a, sizeof(a)); std::sort(set, set + n); int *end = std::unique(set, set + n); for (register int i = 0; i < n; i++) a[i] = std::lower_bound(set, end, a[i]) - set; t.build(a, n); for (register int i = 0, l, r, k; i < m; i++) { read(l), read(r), read(k); register int ans = t.query(l, r, k); std::cout << set[ans] << "\n"; } return 0; }
|