93. 昨日と今日解いた問題(2022.03.31)
昨日と今日解いた問題についてまとめます。
自分で解きたい方のために、最初に問題だけ置いて、後で自分の解法を書きます。
問題一覧
- E - Mex Min (Diff: 1088)
- C - Align (Diff: 1095)
- D - Strange Lunchbox (Diff: 1085)
- E - Amusement Park (Diff: 1084)
前 2 つは、正直緑diffとは思えないほど難しかったです。この問題セットの中では 3 問目が一番楽かな、と思います。
自分の解法など
E - Mex Min
の遷移で変化するのは
- が除外される
- が採用される
のみです。よって、これを上手く計算してやればよさそうです。
について mex を計算するついでに、その数列に なる がいくつ含まれるか Dictionary として保持しておきます。これとは別に、数列に含まれない、非負整数の(重複のない)リストを保持します。mex はこの中で最小の数です。PriorityQueue を使いたいところですが、遷移によって動的な除去が必要なので、MultiSet を使います。遷移ごとに Dictionary と MultiSet を適切に更新していきます。
計算量は ですが、MultiSet の操作が とはいえオーバーヘッド大きめなので若干厳しいです。制約が と大きめなのも厳しいです。重いのは MultiSet で最小値を持ってくる所で、定数倍改善としてこの操作を極力行わないようにしないと間に合いませんでした。
これは…(4 sec制限) pic.twitter.com/vbyuyDdRgc
— イバコ (@ibako_piyo) 2022年3月30日
C - Align
あんまり戦略が浮かばないのでサンプルを見てみます。すると、「大きい数・小さい数・大きい数…」という順に並べていけばなんとなくよさそうに思えます。
という数列を考えてみて、 であれば または を入れ替えた方がよいことが分かります。よって、 または のような並べ方が必要条件になっているといえます。
前者の条件で問題の値を求めると、 のような計算式になります。また、後者の条件では のようになります。式を整理して、以下のようになります( は を並べ替えた数列とします)。
- が奇数のとき
または
- が偶数のとき
または
よって、これを最大化するように数列の項を割り当てればよいです。つまり、加算になっている項は大きい方から、減算になっている項は小さい方から割り当てます。ただし、係数が 1 である項が 2 箇所出てくるので、ここには正であれば「大きい方から」なるべく小さな値、負であれば「小さい方から」なるべく大きな値を割り当てなければなりません。それ以外は、先ほどの条件に従って適当に当てはめればよいです。
結局、数列のソート後にこれらの割当操作をするだけなので、計算量は です。
D - Strange Lunchbox
全探索は無理です。問題文の雰囲気からたぶん DP だろうなー、と思います。
と素直にテーブルを作ってみます。これで行けそうです。
問題はぴったり 個のたこ焼き・ 個のたこ焼きが入手できるとは限らない点です。 という制約があるので、オーバーしても 個分程度です。よって、それぞれ 個分テーブルを用意して、答えを出すときに の範囲を全部見て最小値を出すことにします。
計算量は で大きく見積もって 程度なので十分そうです。
E - Amusement Park
明らかに、満足度の大きなアトラクションに乗り続けるのが最善手です。ただし、 と非常に制約が大きいため、単純なシミュレーションはできません。
そこで、予め を降順に並べた を考えて、順番に項を見つつ以下のようなシミュレーションを行っていきます。ただし、末端の計算は等差数列の和の公式などを用いて定数時間で行います。また、アトラクションに乗れる残り回数に気をつけて、数が足りない場合は除算・剰余を用いて適切な計算式に変更します(式は割愛します)。
- のとき
- のとき
- となるまで を選択し続ける
- のとき
- 何もせず次へ
- のとき
- のとき
- 個のアトラクション全てを 回選択する
ソートが必要なので、計算量は です。