-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathmonotone_minima.cpp
More file actions
64 lines (55 loc) · 1.9 KB
/
Copy pathmonotone_minima.cpp
File metadata and controls
64 lines (55 loc) · 1.9 KB
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
//
// Monotone 行最小値問題 by Monotone Minima
// H x W 行列の各行の min を求める, Monotone 性を仮定 (argmin が単調非減少)
// O(H + W log H)
//
// verified
// COLOCON 2018 Final C - スペースエクスプローラー高橋君
// https://beta.atcoder.jp/contests/colopl2018-final-open/tasks/colopl2018_final_c
//
// Reference:
// tatyam: Monge の手引き書
// https://speakerdeck.com/tatyam_prime/monge-noshou-yin-shu
//
#include <bits/stdc++.h>
using namespace std;
// find min_j f(i, j) for all i, by Monotone Minima, O(H + W log H)
// f(i, j) must be monotone (argmin is not decreasing)
template<class VAL, class FUNC> vector<pair<VAL, int>> MonotoneMinima(int H, int W, const FUNC &f) {
vector<pair<VAL, int>> res(H, make_pair(numeric_limits<VAL>::max() / 2, -1));
auto rec = [&](auto &&rec, int HL, int HR, int WL, int WR) -> void {
if (HR - HL <= 0) return;
int HM = (HL + HR) / 2;
res[HM].second = WL;
for (int i = WL; i < WR; i++) {
VAL val = f(HM, i);
if (res[HM].first > val) res[HM] = make_pair(val, i);
}
rec(rec, HL, HM, WL, res[HM].second + 1);
rec(rec, HM + 1, HR, res[HM].second, WR);
};
rec(rec, 0, H, 0, W);
return res;
}
//------------------------------//
// Examples
//------------------------------//
// COLOCON 2018 Final C - スペースエクスプローラー高橋君
/*
M[i][j] = (j - i)^2 は Monge
列 j に一様に A[j] を加えても Monge
*/
void COLOCON_2018_final_C() {
long long N;
cin >> N;
vector<long long> A(N);
for (int i = 0; i < N; i++) cin >> A[i];
auto func = [&](long long i, long long j) -> long long {
return A[j] + (j - i) * (j - i);
};
auto res = MonotoneMinima<long long>(N, N, func);
for (int i = 0; i < N; i++) cout << res[i].first << endl;
}
int main() {
COLOCON_2018_final_C();
}