解法
は、とりあえず答えに加算すれば良いので、ほとんど無視して問題ないです。ということで、
と
について考えていきます。
の総和を最小化する問題は、
を
の中央値にすればよいです。現在の
がわかっているとき、
となるような
については
、そうでないときは
となります。
中央値を計算する際、必要なのは中央値に近い部分のみです。ということで、より大きい部分と、そうでない部分で2つに分割し、ちょうど中間あたりのみを見ることができるようにします。
ここで登場するのが優先度付きキューです。2つ使用します。
について、値が小さいものについては降順に取り出すことができる優先度付きキューに、値が大きいものについては昇順に取り出すことができる別の優先度付きキューに格納すると、真ん中に近い部分が、2つのキューの先頭に現れます。
あとは、次に追加されると、2つのキューの先頭を見比べ、2つのキューが矛盾しないかつ、サイズの差が常に1以下になるように調整していけば、キューの先頭がちょうど中央値、
になります。
の出力は、2つのキューの総和をあらかじめ求めておいて(キューの更新は要素を1つずつに対してのみなので、要素を入れたり出したりするたびに総和も更新しておけばよいです)、絶対値の計算の定義に合うように調整をします。小さい値が入っているキューの総和を-1倍すればよいです。その後、2つのキューの総和、
の総和と、奇数の場合は
を合わせて計算(小さいキューのサイズが大きい時は
を加算、そうでないときは減算)すれば、答えが求まります。
感想
はじめ、BITでガリガリ計算しようと思っていたのですが、コンテスト後のTwitterでこの方法を聞き、天才だと思いました…
Fまでを全部解ききる力がまだ無いような気がします。