Codeforces Round 1091

A. The Equalizer

スペシャルを使う場合と使わない場合それぞれ考えます.

「使う場合」については使うタイミングに結果がよらないです.

結局 $2$ 種の偶奇を確認すればよいです.

C. Grid Covering

まず,$\gcd(N,a)=\gcd(M,b)=1$ が必要です.

移動は $(a,0)$ と $(0,b)$ ですが,この必要条件のもと,行や列に番号をつけなおせば,移動は $(1,0)$ と $(0,1)$ だとして考えても構いません.

$2$ 手ごとに $(1,1)$ 進みます.これで周期を考えて,全マス埋め尽くせるかを考えます.周期が $NM$ または $NM/2$ であることが必要条件で,後者だけ少し非自明ですがどちらの場合も十分であることが示せます.

D. Flip the Bit (Hard Version)

$x=1$ なら全体をフリップしておくことで,$0$ を作る問題だとしてよいです.

$a_i\neq a_{i+1}$ であるような境界全体に注目します.さらに,$a_0=1$ なら $a_0$ と $a_{-1}$ の間にも仮想的に境界があると考えます.末尾も同様にします.

special を含むという条件をいったん無視すると,操作は「ある場所が異なる値の境界となっているか否かを,ちょうど $2$ 箇所について変更する」というものです.現在境界となっている場所を $2$ 個ずつ減らすのが最適です.

special な要素で区切って,境界がいくつずつあるかを考えます.異なるブロックの境界 $2$ 個は $1$ 手で消せるので,過半数あるブロックがない場合には上の評価が達成できます.ある場所に過半数あるときにはその個数が求めるものとなります.

E. Definitely Larger

$p_i$ が大きいものから順に決めていきます.$q_i$ は値ではなく相対的な位置関係だけを決めて,今まで決めたところに挿入していくことにすると,簡単な必要条件のもと好き放題調整できることが分かります.

F. Interval Game

Grundy 数の一般論から,$L_1,R_1,L_2,R_2$ を固定したときのゲームは,勝敗は $L_1-1,X_1-R_1,L_2-1,X_2-R_2$ の XOR で決まります.

まず,$(L_2-1)\oplus (X_2-R_2)$ の分布(値ごとに何通りの $L_2,R_2$ があるか)を求めておきます.$L_1,R_1$ についても同様にします.

求める分布は言い換えれば次のようになります:$a+b\leq K$ となる非負整数 $a,b$ に対する $a\oplus b$ の分布を求めよ.

桁 dp でこれを処理すれば,$O(K)$ 時間で分布を求められます(例えば $a,b$ の $1$ の位を決めて再帰します).

これらが求まれば,確率最大化も簡単です.先手が実現可能な XOR も上の分布から分かって,そのような XOR に対して負け確率最小化とすればよいです.先手が実現したい XOR をひとつ選んだら,同様の桁 dp でそれを実現する $L_1,R_1$ を求められます.

G. Down the Pivot

まず木と頂点の値を決めたときの最小回数について考えます.このとき,bottom up に,その頂点をパスの端点とするような操作の回数の偶奇が決まります.逆に各頂点ごとの操作回数偶奇を決めると,頂点の値はただひとつ決まります.

すると結局問題は次のようになります.

  • 木と,各頂点への 01 を決める方法を数えてください.
  • 根から見て,left subtree の値の和を $x$,right subtree の値の和を $y$,根自身の値を $z$ とするとき,$\max(x+z,y+z)=K$ となるような方法を数えてください.

$z=0,1$ はどちらも試して,さらに $\max = k$ というのは,「$k$ 以下」と「$k-1$ 以下」の差分で表しておきます.$x,y\leq k$ を数えるというようになります.

left subtree,right subtree の頂点数 $a,b$ を決めると,次の積を足す感じになります.

  • 頂点数 $a$ の binary tree(定義は問題文通り) の作り方
  • 頂点数 $b$ の binary tree(定義は問題文通り) の作り方
  • $\sum_{i\leq k}\binom{a}{i}$
  • $\sum_{i\leq k}\binom{b}{i}$

binary tree の作り方は Catalan 数であることが有名だと思います.

二項係数の prefix sum については,$a,b$ を動かしながらも $k$ は一定で計算すればよいことから,$a=0,1,2,\ldots$ の順に差分更新すれば,全体で $O(N)$ 時間で解けます.

H. Closer

木 DP を頑張る.という解法で解けます.各頂点 $v$ に対して,$v$ の部分木内で発生する最大スコアを求めるのですが,

  • $v$ を動かさないとした場合
  • $v$ の近傍頂点それぞれについて,$v$ とそれをスワップするとした場合

という $O(\mathrm{deg}(v))$ 個の値の最大スコアを計算ということになります.

少し実装がややこしいのは,$v$ を子とスワップするとした場合です.いったん $v$ と各子 $w$ に対して,辺 $vw$ はスワップしない,辺 $vw$ で発生するスコアは無視する,とした場合のスコアの和を求めておけば,あとは子ごとに適切に差分更新できます.

まぁ結局のところ,素直な木 DP でそのまま解けるという発想のあまり要らない問題で,ただし実装しきるのが結構大変というタイプの解法です.

CodeForces
スポンサーリンク
シェアする
maspyをフォローする
maspyのHP
タイトルとURLをコピーしました