mp
1 つの方法は、0 <= j < n ごとに、最初の j 要素の最小値のインデックスを含む配列を構築することです。
int minPos = 0;
for (int i = 0; i < n; ++i) {
if (a[i] < a[minPos]) minPos = i;
mp[i] = minPos;
}
これには明らかに O(n) 時間がかかります。
の要素は、減少する値を持つmp
入力配列の要素を参照します。a
クエリ (i, k) を指定するmp
と、範囲 [0, i - 1] で k のバイナリ検索ができるようになりました。間接参照を使用して、最小インデックスから実際の最小値を取得します。
int find(int i, int k) {
int start = 0;
int end = i - 1;
if (a[mp[end]] >= k) return -1; // Not found.
if (a[mp[start]] < k) return mp[start]; // The first element is smaller.
// We maintain the invariant that a[mp[start]] is >= k and a[mp[end]] is < k.
while (end - start > 1) {
int mid = (start + end) / 2;
if (a[mp[mid]] < k) {
end = mid;
} else {
start = mid;
}
}
return mp[end];
}