Codeforces Round #530

published: ,
last modified: .

lang: ja

category: competitive_programming

tags: codeforces ocaml

A. Snowball

問題文に書かれている処理をそのまま実装. 解答例

B. Squares and Segments

解答例

横幅および縦幅を広げてしまうと必要なSegment数が増えるため,なるべく正方形に収まるようにするのが最適.対称性より横幅\ge縦幅とする.すると横幅はnn個以上入る正方形の一辺ppとすればよい[1]p×pnp \times p \ge nよりpnp \ge \sqrt{n}となり,ppは整数であるからceil(n)ceil(\sqrt{n})が最適.縦幅は余り部分も必要であるからceil(n/ceil(n/(横幅)))として求まる.

別解(editorial)

求めたい値は縦幅と横幅をpp,qqとしたときmin{p+q} s.t. p×qn\min{\{p+q\}} \text{ s.t. } p \times q \ge nである.ここでqp2|q-p| \ge 2は無駄:例えばp=3,q=5p=3,q=5のとき15個までしか入らないが,p=q=4p=q=4とすればp+q=8p+q=8を保ちつつ16個入れることが可能.p=3,q=6p=3,q=6のときもp=4,q=5p=4,q=5とすることで2個分得する.これは要するに先の「横幅および縦幅を広げると必要なSegment数が増える」に対応し,気持ちとしては「横幅と縦幅を近づけて正方形に近くしたい」という認識でよい気がする.

従って解は対称性より(p,q)=(r,r)(p,q)=(r,r)または(r,r+1)(r,r+1)という形に限られる.editorialではr=floor(n)r=floor(\sqrt{n})とした後で(r,r),(r,r+1)(r,r),(r,r+1), さらに丸めについても考えて(r+1,r+1)(r+1,r+1)も試している.rr11からceil(n)ceil(\sqrt{n})まで動かして確かめてもO(n)O(\sqrt{n})で間に合うし,この方針を採っている人が多い印象.

C. Postcard

解答例

とりあえず記号(とそれとペアの文字)を消去したものttを考える.この文字列は必ず残るため,t|t|kkより大きいとImpossible.等しければそのまま出力.小さければ記号の利用を考える.まず'*'があればこれ1個から任意文字数作ることが可能なため,適当な1つをktk-|t|文字出して残りの'*'及び'?'を0文字にすればよい.無い場合は'?'を使う:ktk-|t|個以上'?'があればその数だけ文字を出現させればよい.足りなかったらImpossible.

最初書き直したときに「i番目を見ているとき,'*'がi+2番目にあれば~~」という処理を採用していたのだが,これは先頭がa*などのときに不発になる.

D. Sum in the tree

解答例

解法

editorialがよく分からなかったので自分流に書き換えてみた.よって誤りがあるかも.

求めるべき値がai\sum a_iの最小値であるから,aia_iの値はなるべく増やしたくない. まず偶数深さの葉iiについてはaia_iを何にしようが他の頂点に影響しないため,素直にai=0a_i=0とできる.

葉でない場合はどうするか.ここで頂点iiの親をpp, iiの子をc1,...,ckc_1,...,c_kとする.いまsi=sh+ais_i = s_h + a_i, scj=si+acjs_{c_j}=s_i+a_{c_j}である.a\sum aを最小化したいという要請に合わせて変形するとacj=scjsi=scjshaia_{c_j} = s_{c_j} - s_i = s_{c_j} - s_h - a_i.前2項は奇数深さゆえ所与であるから,aia_iの値を決めればacja_{c_j}も決まる,すなわちaia_iの値に応じiiすべての子について値acja_{c_j}が変化する.aia_iを1増やすとacja_{c_j}が1減るから,acj\sum a_{c_j}kk減ることとなる.よってaia_iをできるだけ大きく取って損することはない(k<1k \lt 1,すなわちiiが葉の場合を除くが,これは先に議論した). aaの各要素は0以上であるから,aia_iの最大値はacj=0a_{c_j}=0が現れるときであり,ai=min{scj}sha_i=\min\{s_{c_j}\}-s_hとなる.構成不可能な場合はこれが0未満になってしまうか否かで判別可能.

気持ちとしては「aia_iを小さく持ってしまうと,子らがscjs_{c_j}を再現するために各acja_{c_j}にその分を持たなければならず,a\sum aが増大する.よってaia_iで出来るだけ負担してあげる」という感じ.

実装はDFSでよい.奇数深さ頂点の場合はai=sisha_i = s_i - s_hの左辺がすべて所与であるからこの式で求まる.偶数深さ頂点の場合は先に述べた処理をそのまま行えばよい.

もう少し簡潔な考察?:sis_iが取れる値の範囲に着目すると[sh,min{scj}][s_h, \min\{s_{c_j}\}] となる.対応するaia_iの値は[0,min{scj}sh][ 0, \min\{s_{c_j}\} - s_h].先の議論からaia_iは大きいほうがよいので右端を採用.


  1. 横幅,縦幅をw,hw,hとする.wwpp未満であるとするとき,whw \ge hであったからwhww(p1)2<nwh \le ww \le (p-1)^2 \lt n\because ppの定義(p1)2<np2(p-1)^2 \lt n \le p^2)となりnn個入らない.反対にwwppより大きいときを考える.w=pw=pのときのhhqqであるとすると,w=p+1w=p+1のときのhhqq以下になる(\because npqn \le pq, n(p+1)hn \le (p+1)hよりq=ceil(n/p)q=ceil(n/p), h=ceil(n/(p+1))h=ceil(n/(p+1)))から縦横の差が広がって正方形から遠ざかる. ↩︎