ABC144 E - Gluttony
問題原文
問題要旨
人のメンバーと、 種類の食べ物がある。 番目のメンバーの消化コストは で、 食べ物 の食べにくさは である。
一人のメンバーに対して、一つの食べ物を割り当てる。 この時、そのメンバーが食べ物を完食するのには、 (そのメンバーの消化コスト) × (その食べ物の食べにくさ) 秒だけかかる。
以下の操作が 回許されている時、各メンバーに対して食べ物を適切に割り当てた時の、 (そのメンバーの消化コスト) × (その食べ物の食べにくさ) の最大値を求めよ。
操作
消化コストが1以上のあるメンバー一人の消化コストを1減らす
解法
明らかに 消化コストが低いメンバー順に、食べにくさが大きい食べ物を割り当てていくのが最適。 この食べ物の割り当ては固定。
以降各メンバーのコストを、上記の割り当てを行った上で、とする。
操作を行うべきメンバーは、 が最大のメンバー。
優先度付きキューで管理すれば、最大のメンバーを取り出す操作は でできるが、 操作回数がバカでかいのでシミュレーションはできない。
答えに単調性があることに気づく。つまりにぶたんができる。
答えを にすることができるかどうかは、各メンバーの を 以下にするために何回修行したかによる。
あるメンバーについて、 を 以下 にするために必要なコストは、適に式変形して (小数点以下切り捨て)となる。
これでにぶたんができるようになって、解ける。
実装
達成不可能が画定したらにぶたんを打ち切るのがいい。
N, K = map(int, input().split()) A = sorted(list(map(int, input().split()))) F = sorted(list(map(int, input().split())), reverse=True) # にぶたん := N人のメンバーそれぞれが完食にかかる時間のうち最大値をxに以下にできるか? ok, ng = 10 ** 12 + 1, -1 while ok - ng > 1: x = (ok + ng) // 2 need_training = 0 for a, f in zip(A, F): need_training += max(0, a - x // f) if need_training > K: ng = x break else: ok = x print(ok)
感想
にぶたん典型〜〜教育的な問題だと思います。