給定長度 n ≤ 100,000 的數組 a[1..n](互不相同),m ≤ 5,000 個查詢 Q(i, j, k):求區間 [i, j] 排序後第 k 小的數。數值絕對值 ≤ 10^9。
1..n 的排名。n 棵線段樹版本 root[i] 表示前綴 [1..i] 的值頻率統計。root[i] 由 root[i-1] 插入 a[i] 得到,只新建 O(log n) 個節點,共享其餘。[l, r] 第 k 小:利用 root[r] - root[l-1] 的差值,在線段樹上二分(比較左子樹計數與 k)。struct Node {
int l, r; // 左右孩子索引
int cnt; // 該區間元素個數
} tree[MAXN * 20]; // n log n 節點
int roots[MAXN];
int tot = 0;
void insert(int& cur, int pre, int l, int r, int pos) {
cur = ++tot;
tree[cur] = tree[pre];
tree[cur].cnt++;
if (l == r) return;
int mid = (l + r) >> 1;
if (pos <= mid) insert(tree[cur].l, tree[pre].l, l, mid, pos);
else insert(tree[cur].r, tree[pre].r, mid+1, r, pos);
}
int query(int u, int v, int l, int r, int k) { // u=root[r], v=root[l-1]
if (l == r) return l;
int left_cnt = tree[tree[u].l].cnt - tree[tree[v].l].cnt;
int mid = (l + r) >> 1;
if (k <= left_cnt) return query(tree[u].l, tree[v].l, l, mid, k);
else return query(tree[u].r, tree[v].r, mid+1, r, k - left_cnt);
}
n, m,數組 a。sorted = a,排序去重。for i=1..n: insert(roots[i], roots[i-1], 1, n, rank(a[i]))。idx = query(roots[r], roots[l-1], 1, n, k),輸出 sorted[idx]。