[洛谷P3834] 【模板】可持久化线段树 1(主席树)
题目大意:静态区间第K小
题解:主席树
卡点:无
C++ Code:
#include <cstdio> #include <algorithm> #define maxn 200010 #define maxm 12000010 using namespace std; int rt[maxn], lc[maxm], rc[maxm], num[maxm], idx; int n, m, x, y, k; int s[maxn], rnk[maxn], p[maxn]; inline bool cmp (int a,int b){return s[a] < s[b];} void add(int &cur, int ver, int l, int r, int x) { cur = ++idx; lc[cur] = lc[ver]; rc[cur] = rc[ver], num[cur] = num[ver] + 1; if (l ^ r) { int mid = l + r >> 1; if (x <= mid) add(lc[cur], lc[ver], l, mid, x); else add(rc[cur], rc[ver], mid + 1, r, x); } } int ask(int L, int R, int l, int r, int k) { if (l == r) return s[rnk[l]]; int t = num[lc[R]] - num[lc[L]], mid = l + r >> 1; if (k <= t) return ask(lc[L], lc[R], l, mid, k); else return ask(rc[L], rc[R], mid + 1, r, k - t); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++)scanf("%d", &s[i]), rnk[i] = i; sort(rnk + 1, rnk + n + 1, cmp); for (int i = 1; i <= n; i++) p[rnk[i]] = i; for (int i = 1; i <= n; i++) rt[i] = rt[i - 1], add(rt[i], rt[i - 1], 1, n, p[i]); while (m--) { scanf("%d%d%d", &x, &y, &k); printf("%d\n", ask(rt[x - 1], rt[y], 1, n, k)); } return 0; }