Codeforces Round #521 (Div. 3)D. Cutting Out
問題概要
長さ の数列 と非負整数 が与えられる. に対して, 長さ の数列 の Cutting Out を以下のように定める :
- の各要素を一回ずつ から削除する. もし 削除できない要素がひとつでもある場合, Cutting Out はできない.
の要素は重複することができるため, の要素をすべて が含んでいても Cutting Out できない場合があることに注意せよ. 例えば, のとき, の要素を はすべて含んでいるが, を 回削除することはできないので Cutting Out ができない.
このとき, 適切に を定めることにより連続してできる Cutting Out の回数を最大化したい. どのように を定めればよいか?
制約
解法
貪欲にやってうまくいかなさそうな最大化の問題は, 二分探索を考えるとうまくいくことが多々あります. この問題でも二分探索を考えてみましょう.
回 Cutting Out することは可能か?という判定問題を考えます. がある要素を 個含んでいるとき, 回 Cutting Out するにはこの要素は には 個までしか含むことができません. そこで, の全ての要素について, に含むことができる要素の個数を総和して, これが 以上ならば 回の Cutting Out が達成できて, 逆に 未満ならばどうやっても 回はかないません.
この判定問題は で解くことができるので, 全体として で問題を解くことができました.
実装
std::map を用いているので計算量は となっています.