Tenka1 Programmer Contest (2018) C - Align
解法
解説に詳しい証明が載っているのですが、並べた後の数列が凸凹になっていると、効率がよりよくなります。
みたいな感じです(逆もあり得ます)。
このとき、以下のような図で表現できます。上にある頂点は隣の数より大きく、下にある頂点は隣の数より小さいです。
さて、このときの差の絶対値の計算はというと、
となります。
が増えると、2倍して足す部分、もしくは引く部分が交互に追加されていきます。
この中で、数字をどのように使って行くのが一番いいのかというと、
より大きい数字は、2倍して加算する部分
より小さい数字は、2倍して減算する部分
となります。ただし、端の2箇所だけ、2倍されずに加算、もしくは減算される部分が存在するので、この部分だけ調整します。
これは、この数字をソートしたとき、中央の2個(もしくは3個)の数字を見るだけで大丈夫です。これは、偶奇で場合分けをしてあげるとスッキリいきます。そして、それ以外は、先ほどの条件にしたがって先に計算してしまいます。が奇数の場合
中央の3つだけを取り出して考えると、上記のような2パターンに絞られます。
上はであり、
下はです。
先ほども述べたように、2倍して加算する部分はできるだけ大きい数字を、2倍して減算する部分はできるだけ小さい数字を選ぶのがいいので、3種類の数字を小さい順にと名付けてあげると、先ほどの2パターンそれぞれについての最大値は
となります。
あとは、この2つのうち大きい値を選んであげればよいです。
- が偶数の場合
実は、左右対称です。最初と最後は、常にどちらかが上側で、もう一方が下側に存在します。
ということで、中央付近の値 (ただし )を2つ持ってきたときに、
とのうち値が大きい方を選択すればいいわけです。
というわけで、最初に求めた、2倍して加算したり減算した結果と、偶奇に分けて考えた中央付近の結果を足し合わせれば答えとなります。