トピックの説明
タイトルのように、n 個の整数で構成されるシーケンス a が与えられると、指定された閉区間 [l,r] 内の k 番目に小さい値がクエリされます。
入力フォーマット
最初の行には、シーケンスの長さ nn とクエリの数 m をそれぞれ表す 2 つの整数が含まれています。
2 行目には n 個の整数が含まれており、i 番目の整数はシーケンスの i 番目の要素 ai を表します。
次の m 行のそれぞれには、クエリ間隔 [[l,r]] 内の k 番目に小さい値を表す 3 つの整数 l、r、k が含まれています。
出力フォーマット
クエリごとに、答えを表す整数を行に出力します。
入力サンプルと出力サンプル
#1 を入力してコピーします
5 5 25957 6405 15770 26287 26465 2 2 1 3 4 1 4 5 1 1 2 2 4 4 1
#1 のコピーを出力します
6405 15770 26287 25957 26287
問題解決のアイデア:
永続線分ツリーは、基本線分ツリーを単純に拡張したもので、履歴バージョンのクエリをサポートし、履歴バージョン間の共有データを使用して時間とスペースの消費を削減することが特徴です。
これに含まれるアイデアには、プレフィックスとアイデア、共通点、離散化、ウェイト ライン セグメント ツリー、および動的開始点が含まれます。
ウェイト ライン セグメント ツリーを記録する場合、毎回新しいツリーを開いてノードの値を記録することは不可能です。
これは、動的な開始点を考え、ルート ノードを記録し、変更されたノードとその子ノードの値を記録するための新しいスペースを開くことです。
プレフィックス合計を使用するアイデアは、以前に記録された長期ノードの値と、後でオープンされたノードの値の差が、新しく追加されるノードの数であるということです。区間 [L,R] には、区間 [1,R] から区間 [1,L-1] を引いたものに等しい要素が含まれます。
問題解決コード:
#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
int cnt = 0;
int a[N], b[N], root[N];
struct {
int L, R, sum;
}tree[N<<5];
int update(int pre, int pl, int pr, int x) {
int rt = ++cnt;
tree[rt].L = tree[pre].L;
tree[rt].R = tree[pre].R;
tree[rt].sum = tree[pre].sum + 1;
int mid = (pl + pr) >> 1;
if (pl < pr) {
if (x <= mid) {
tree[rt].L = update(tree[pre].L, pl, mid, x);
}
else {
tree[rt].R = update(tree[pre].R, mid + 1, pr, x);
}
}
return rt;
}
int query(int u, int v, int pl, int pr, int k) {
if (pl == pr) return pl;
int x = tree[tree[v].L].sum - tree[tree[u].L].sum;
int mid = (pr + pl) >> 1;
if (x >= k) {
return query(tree[u].L, tree[v].L, pl, mid, k);
}
else {
return query(tree[u].R, tree[v].R, mid + 1, pr, k - x);
}
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
b[i] = a[i];//离散化
}
sort(b + 1, b + 1 + n);
int size = unique(b + 1, b + 1 + n) - b - 1; // 不重复的个数
for (int i = 1; i <= n; i++) {
int x = lower_bound(b + 1, b + 1 + size, a[i]) - b;
root[i] = update(root[i - 1], 1, size, x);
}
while (m--) {
int x, y, k;
cin >> x >> y >> k;
int t = query(root[x - 1], root[y], 1, size, k);
printf("%d\n", b[t]);
}
return 0;
}