公式

I - Damage over Time 解説 by m_99


モンスターの体力が \(0\) 以下になったら終了するものとして、最後から \(i\) 番目のターンに魔法 \(j\) を使うとその魔法は終了までに \(\min (i, t_j) \times d_j\) のダメージを与えます。各ターンで使うべき魔法はこの値が最大となるものです。
\(t_j\) として現れる値を \(t'_1,\lt\ldots,\lt,t'_{N'}\) とし、\(N'+1\) 個の区間 \([0, t'_1), [t'_1, t'_2), \ldots,[t'_{N'-1}, t'_{N'}), [t'_{N'}, \infty)\) を考えます。また、\(i \lt t_j\) となる魔法の添え字の集合を \(X\)、そうでない魔法の添え字の集合を \(Y\) とします。すると、\(X,Y\)\(i\) がどの区間に属しているかによって変化します。この区間ごとに与えられるダメージの最大値を考えてモンスターの体力が減る様子を \(\mathrm{O}(1)\)\(\mathrm{O}(\log H)\) でシミュレーション出来れば本問を解くことが出来ます。

\(X,Y\) に対し、与えられるダメージの最大値は \(\max ( i \times \max_{j \in X} d_j, \max_{j \in Y}t_j \times d_j)\) です。この値の区間内での総和は、\(\max\) 関数内での前者が後者より大きくなる \(i\) を割り算で求め、等差数列の和の公式を使うことで \(\mathrm{O}(1)\) で求められます。これでモンスターの体力が残る場合は減らした上で次の区間へ行き、そうでなければ二分探索等で初めてモンスターの体力が \(0\) 以下になるターンを求めれば良いです。オーバーフローに注意してください。

投稿日時:
最終更新: