Codeforces Round #494 のバチャをしました、Bで50分かかってしまい、4完でした。
翌日にEまで解いたので、自分の方針を説明します。
A. Polycarp's Pockets
一番種類数の多いコインの数だけポケットがあれば必ず重複なしに振り分けられます。
C++のstd::mapを使うとでできます。
std::unordered_mapを使うとでできます。
B. Binary String Constructing
ここはつまづいたので詳しめにいきます。
問題概要
個の0と個の1を並べて、となるの数がとなる文字列を構成しなさい。入力のもとで、答えが必ず存在することは保証される。
解説
のときだけ取り上げます。
1. をこ並べる
2. を個並べる
3. を個並べる
証明
1. で並べた文字のうち、最後の一つを除いた文字はを満たす。
のとき
が言えるので必ず3. でを配置でき、
3. でを並べる前の数列の最後の数字は必ずであり、
一つ後ろにが来ることでを満たすようになる。
以上より、を満たすの数がx個になる。
の時はとを入れ替えて同じことをしてください。
が奇数の時は2. と3. を入れ替えて操作を行ってください。(このときは切り捨ててください。)
C. Intense Heat
あらかじめの累積和を取っておくと、任意の区間でのがで取得できます。
となる長さxの区間それぞれの平均値の最大値を求めれば良いです(読解が一番時間がかかりました)。
D. Coins and Querys
全てのについて、を計算し、その数を配列などに保持します。
与えられるについて、にたっているフラグを上から見ていき、取れるコインから取っていきます。
取りきれなかったフラグの分は変数などに入れて管理します。
がまで進んだ時にであれば取ったコインの数を出力し、そうでなければ-1を出力します。
E. Tree Constructing
のとき、明らかに構築できません。
また、のとき、以外の場合構築できません。
これら以外の場合について考えます。
まず、与えられた頂点数でのk分木を考えます。
このときの直径が与えられた条件下で実現できる最小の直径になるので、この木の直径がより大きかったら答えは"NO"です。
次に、直径となるパス上の頂点に印をつけます。
直径の端点を根とする木を再構築します。
ここまでで"NO"を出力していないのなら、木の直径を増やしていけばいつかは条件を満たします。
この木の直径がと一致するまで、色の付いていない頂点を色の付いている葉に接続することを繰り返したら終わりです。
editorial解は最初に直径、頂点数の木を作り、条件を満たしつつ残りの頂点を木に接続していくという方針でした。
たぶんeditorial解の方が実装が楽です。