公式
B - 展望台選び / Choosing an Observation Deck 解説
by
B - 展望台選び / Choosing an Observation Deck 解説
by
MtSaka
問題文の指示通りに \(L,R,V\) を \(H\) に対する更新が発生するたびに計算しなおせばよいです。
\(L,R,V\) の計算は時間計算量 \(\mathrm{O}(N^2)\) でできて、クエリ数 \(Q\) のため全体で時間計算量 \(\mathrm{O}(QN^2)\) で解くことができます。
今回の問題では有理数が出てくるので実装に注意が必要です。一般に実数を扱う場合は競技プログラミングでは double 型や long double 型を使うことが多いです。ですが、誤差によって不正解になる場合があるので有理数で処理できる場合は分母と分子の整数を持って四則演算を行うようにするとよい場合があります。
ですが、この問題は double 型での計算でも正解することができます。
実装例(C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, q;
cin >> n >> q;
vector<int> h(n);
for (auto& e : h) cin >> e;
vector<double> v(n), l(n), r(n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
l[i] = max(l[i], (double)h[j] / (i - j));
}
for (int j = i + 1; j < n; ++j) {
r[i] = max(r[i], (double)h[j] / (j - i));
}
v[i] = 1.0 / (1 + l[i] + r[i]);
}
for (int i = 0; i < q; ++i) {
int t;
cin >> t;
if (t == 1) {
int x, val;
cin >> x >> val;
x--;
h[x] = val;
for (int i = 0; i < n; ++i) {
l[i] = r[i] = 0;
for (int j = 0; j < i; ++j) {
l[i] = max(l[i], (double)h[j] / (i - j));
}
for (int j = i + 1; j < n; ++j) {
r[i] = max(r[i], (double)h[j] / (j - i));
}
v[i] = 1.0 / (1 + l[i] + r[i]);
}
} else {
int a, b;
cin >> a >> b;
a--;
double ans = v[a];
int idx = a;
for (int i = a + 1; i < b; ++i) {
if (ans < v[i]) ans = v[i], idx = i;
}
cout << idx + 1 << endl;
}
}
}
投稿日時:
最終更新:
