E - Cookies 解説
by
kyopro_friends
原案:kyopro_friends
この問題は、最も美味しさの和が大きな選び方から少しずつ妥協していく過程を、プライオリティーキューを用いてシミュレーションすることで解くことができます。
\(A_i\) をソートすることで、\(A_1\geq A_2 \geq \ldots\) であるとしてよいです。
\(i\) 種類目のクッキーを \(C_i\) 枚選ぶ選び方を、長さ \(N\) の数列により \((C_1,\dots,C_N)\) と表すことにします。
クッキーの選び方 \((C_1,\dots,C_N)\) に対し、\(C_i\neq 0\) であるような \(i\) により \((C_1,\dots,C_{i-1},C_{i}-1,C_{i+1}+1,C_{i+2},\dots)\) の形で書くことのできるものを、一段階妥協した選び方と呼ぶことにします。一段階妥協したクッキーの選び方の美味しさの和は、妥協前のクッキーの選び方の美味しさの和以下なので、美味しさの和の上位から選び方を調べるとき、妥協前の選び方が調べられるまで一段階妥協した選び方が調べられる必要はありません。またどの選び方も \((K,0,0,\ldots)\) から一段階妥協を繰り返すことで到達できます。
よって、美味しさの和と選び方の組をプライオリティーキューで管理しながら、キューから要素を取り出した際に一段階妥協した選び方をキューに追加することで、美味しさの和の順に取り出すことができます。既にキューに追加済みのものを再度追加しないよう注意してください。\(1\) 個の要素をキューから取り出すごとに高々 \(N\) 個の要素がキューに追加されるので \(X\) 番目までを求めることは \(O(NX\log(NX))\) 時間ででき、この問題が解けました。
類題
bonus
\(N\) の上限が \(10^5\) で、他の制約は元と同じ問題を解いてください。
解法
本質的な解法は既に述べたものと同じです。妥協の仕方を変えます。「末尾の非0要素を1つ手前へ戻す」が逆操作となるような妥協を考えます。妥協先は高々 \(2\) 通りしかありません。例えば \((2,2,0,0)\) からは \((2,1,1,0)\) 及び \((1,3,0,0)\) へ、\((2,0,2,0)\) からは \((2,0,1,1)\) への妥協となります。妥協の逆操作が一意であることから、妥協により各選び方を得る手順も一意であり、ある選び方が既にキューにあるかどうかを管理する必要はありません。またこれらの妥協とそれによる美味しさの和の変化は、「末尾の非0要素の位置と値」「その1つ前の要素の値」の情報のみで定まるため、\(O(1)\) 個の情報で管理できます。以上より \(O(N\log N+X\log X)\) で解くことができます。
実装例(C++)
投稿日時:
最終更新:
