O - Marunomi for All Prefixes 解説
by
harurun4635
簡単のために、\(i \ne j \Rightarrow a_i \ne a_j\) とします。
スライムを常に Sort 順にすることにします。このとき、あるスライム \(i\) がスライム \(i+1\) に勝利するための条件は \(\displaystyle \sum_{0 \le j \le i} a_j > a_{i+1}\) です。
スライム \(i\) を固定したとき、スライムの挿入にたいして、左辺は単調増加、右辺は単調減少となります。(挿入によって、スライム \(i+1\) が違う重さになることもあります)
よって、「勝利できるかどうか」には単調性があり、これは簡単には並列二分探索を用いることで、すべての \(0 \le i \lt N\) に対して、 \(O(N \log^2 N)\) で求めることができます。
この情報を用いて、問題をときましょう。問題にこたえるためには、各スライムの勝利数を常に管理すればよいです。
「スライムの挿入」・「勝利できるようになる」による変化は、上の情報を用いることで、いくつかの区間にたいする加算になります。(実際には総和のみに興味があるので、どれだけ増減するかを適切に管理できれば十分です)
これは、\(O(N\log N)\) で可能です。
よって、\(i \ne j \Rightarrow a_i \ne a_j\) の条件下では解くことができます。
そうでないときは、適当なタイブレークをすれば基本的にはこたえる事ができます。気をつけるのは、最小値の要素が複数あるときです。このときのみ上の条件が破綻しますが、これによる答えの変化は簡単に計算することができます。
よって \(O(N \log^2 N)\) でこの問題を解くことができます。
計算量のオーダーは公式解説よりよいですが、実行時間制限が厳しいです。 C++であっても、いくつかの定数倍高速化が必要になりそうです。
投稿日時:
最終更新:
