【AtCoder】ABC 482 D - Wannabe Zombie

実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 766 / NoviSteps: 1Q / 配点: 400 点
問題概要
数直線上に人 の 人が立っており、人 が立っている座標は である。
各 について、以下の問題を解け。
時刻 に人 がゾンビになり、人 以外は人のままである。 時刻 以降、人またはゾンビは数直線上を単位時間あたり 以下の速さで自由に移動できる。 ゾンビと人が同じ座標にいると、その人はゾンビになる。 全員がゾンビになる時刻として考えられる最小値を求めよ。
なおこの問題の制約下において、求める答えは整数になることが証明できる。
制約
- は偶数
- 入力は全て整数
考察
のときは明らかに である。 以下、 の場合を考える。
全員がゾンビになる最小値を求めるので、各々が移動できる速さは であるとしてよい。 2人が互いに速さ で近づくと、距離 を縮めるのに必要な時間は である。
また、一度ゾンビが2人になれば、それぞれが左右に移動することで感染を広げることができる。
したがって、人 が最初に左右どちらの人(人 または人 )に感染させるかを考えればよい。
人 に感染させる場合(右に感染させる場合)
この場合、最初のゾンビ が右に進み、人 が左に進む。 すると、2人は時刻 に座標 で出会って、人 がゾンビになる。
その後、2人のゾンビが左右に分かれる。
時刻 時点でこの2人から最も離れているのは、人 と人 である。 両者も時刻 からそれぞれ左右に移動しているので、時刻 時点で、それぞれ座標 と にいる。
人 が時刻 以降にも右に動き続けて人 に感染させる場合、最も早く右端に感染できる時刻は、
である。
一方、人 が時刻 以降にも左に動き続けて人 に感染させる場合、最も早く左端に感染できる時刻は、
である。
したがって、この場合の答えは である。
人 に感染させる場合(左に感染させる場合)
この場合、最初のゾンビ が左に進み、人 が左に進む。 すると、2人は時刻 に座標 で出会って、人 がゾンビになる。
前項と同様に考えると、人 が時刻 以降にも左に動き続けて人 に感染させる場合、最も早く左端に感染できる時刻は、
である。
一方、人 が時刻 以降にも右に動き続けて人 に感染させる場合、最も早く右端に感染できる時刻は、
である。
したがって、この場合の答えは である。
以上をまとめると、各 について、全員がゾンビになる時刻の最小値は、
となる。
これはそれぞれ定数時間で計算できるので、全体として の計算量で解くことができる。
なお、実装時は と の場合分けに注意すること。
実装例
1.#include <bits/stdc++.h>2.using namespace std;3. 4.#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)5. 6.constexpr long long INFL = 1e+18;7. 8.using ll = long long;9. 10.template <typename T>11.inline bool chmin(T& a, T b) { return ((a > b) ? (a = b, true) : (false)); }12. 13.// ======================================== //14. 15.int main()16.{17. int N;18. cin >> N;19. 20. if (N == 1) {21. cout << 0 << endl;22. return 0;23. }24. 25. vector<ll> X(N);26. rep(i, 0, N) cin >> X[i];27. 28. rep(k, 0, N) {29. ll ans = INFL;30. if (k > 0) {31. chmin(ans, max((X[k] - X[0]) / 2, (X[N - 1] - X[k - 1]) / 2));32. }33. if (k < N - 1) {34. chmin(ans, max((X[k + 1] - X[0]) / 2, (X[N - 1] - X[k]) / 2));35. }36. 37. cout << ans << endl;38. }39. 40. return 0;41.}実装時間: 30 分
コメント
A問題じゃなくてこっちがハロウィン問題だったのかもしれない。





