Codeforces Round 584

A. Paint the Numbers

最小要素とその倍数をある色で塗り削除する,という貪欲をして構いません.最小要素を $a$ として,その倍数 $b$ が別の色の最小要素である場合,$b$ の色をすべて $a$ の色に変更できるからです.

B. Koala and Lights

$2,4,6,8,10$ の公倍数である $120$ の周期があるので,適当な範囲を探索すればよいです.

C. Paint the Digits

インデックス昇順に,なるべく後に数を足しやすいように $2$ 色に分けていく貪欲アルゴリズムがあります.

D. Cow and Snacks

お菓子を頂点,人を辺と見てグラフの問題だと思うことにします.「辺をうまい順番に見ていく.辺の端点の少なくとも一方が初めて出てきた頂点だと加点」というようになります.

$n$ 頂点の連結成分からは,$n-1$ 点までしか獲得できません.初手で $2$ 頂点を使うからです.

$n-1$ 点獲得することは可能です.これは適当な全域木をとって,根側から連結性を保つように辺を足していくようにすればよいです.

E2. Rotate Columns (hard version)

max の和の最大化なので,自由に選んで最大化と思ってよく,だいたい次の形です.

  • 各列を自由に rotate して,いくつかの要素に印をつける.
  • 最終的にすべての行にひとつずつ印をつけて,印のついた数の総和を最大化したい.

各列の使い方は,印をつける行集合という $2^n$ 通りがあり,これでひとまず $O(m\cdot 3^n)$ 時間では解けます.

列を,列最大値降順にソートしたとします.このとき,最適解であって次を満たすものが存在します:$i<j$ かつ第 $j$ 列がひとつ以上印を含むならば,第 $i$ 列もひとつ以上印を含む.

これはそうでないとして,第 $j$ 列の印をひとつやめて第 $i$ 列に付け直す操作を考えると証明できます.列の rotate が許されているので,列最大値を好きな行に配置できるというのがポイントです.

よって,列数が $M$ 以下として解けばよくて,$O(M\cdot 3^M)$ 時間になります.

F. Koala and Notebook

まず無向辺は $2$ つの有向辺に置き換えます.さらに番号 $123$ の有向辺は,重み $1$, $2$, $3$ の $3$ つの有向辺で置き換える(間に $2$ つの頂点を挿入する)というようにして,すべての辺はひとつの digit に対応するとします.

単に BFS をすれば,各頂点までの「最短路整数」の桁数が分かります.

桁数が $0, 1, 2, 3, \ldots$ である頂点の順にその点までの最短路を確定させていきます.

桁数が $d$ であるような頂点について,そこまでの「最短路整数」自体を保持する必要はなく,答を求めるための $\pmod{10^9+7}$ での値と,同じ桁数の整数の間のソート順だけ保持すれば十分です.これがあれば,一桁追加したときのソート順がまた分かるので,何もかもが順に計算できるようになります.

G2. Into Blocks (hard version)

まずクエリを無視して答を求める方法を考えます.ある数 $x$ の最初の出現を $L_x$,最後の出現を $R_x$ とします.区間 $[L_x, R_x]$ と $[L_y, R_y]$ が重なるならば,これらは同一の値にする必要があります.このように考えると,結局,区間を交わるという関係で連結成分分解することが要求されていると分かります.

操作コストも含めて考えると,(操作しない要素を数えることにして)次のような問題になります.

  • $(l_x,r_x,w_x)$ という組の集合を管理する.$[l_x,r_x]$ という区間で重み $w_x$ が割り当てられているということを意味する.
  • 区間が交わるという関係で連結成分分解したとき,各連結成分に含まれる区間重みの max の総和を求めよ.
  • 区間の削除や追加が $O(N+Q)$ 回来ます.

これは計算量を無視すれば,おおよそ次のようにして解けます.

  • ある場所に区間がいくつあるかという列 cnt を管理する.$[l_x,r_x]$ という区間があるときこの範囲に区間加算するようにする(より詳細には連結成分の境界を判別できるように端点には足さないなどの調整をする).
  • さらにインデックス $l_x$ に重み $w_x$ を置いておく.
  • 求値では,cnt[i]=0, cnt[j]=0 かつこの間では cnt が正であるときに,この間に置かれた $w$ の max を答に加算する.

これはさらに,次のようにシミュレーションできます.

  • ANS, val という $2$ つの値を用意する.$i=0,1,2,3,\ldots$ 順に次を行う.
  • $cnt[i]=0$ であるとき,ANS に val を足し,val を $0$ にリセットする.
  • そうでないとき,val をそこに置いてある重みで chmax する.

これを平方分割で処理します.(ところでセグメント木でもよかったか)

各ブロックでは,cnt への定数加算については lazy として持っておきます.求値クエリでは,lazy>0 のときは val への chmax が来るだけなので簡単です.lazy=0 で最小値が $0$ のときに何が起こるかは,$cnt[i]=0$ となる最初の $i$,最後の $i$,やその左右,間での max などを前計算しておけばよいです.

H. Moving Walkways

歩道がない場所は速度 $0$ の歩道があると思って,全体を歩道の列としておきます.各境界のところで,次のような dp 関数を考えます:

  • ある時刻 $t$ にその地点に到達する場合に,その時点で保持しているエネルギーの最大値が $x$ であるとき,$\dp[t]=x$ とする.

速度 $s$ で長さ $d$ の歩道を挟んだときに,どのような遷移が可能かを考えます.$(t_1,x)$ から $(t_2,y)$ に遷移するとします.次のような条件があります.

  • $y\geq 0$:エネルギーが枯渇していない.
  • $0\leq d-s(t_2-t_1)\leq 2(t_2-t_1)$:自分の歩行速度が $[0,2]$.
  • $y=x+(1+s)(t_2-t_1)-d$:エネルギーの収支.

最後の条件から,$(t_1,x)$ から $(t_2,y)$ へは,$-d$ 平行移動したあとで傾き $1+s$ の直線上のどこかに行けるということになっています.

$2$ 番目の条件は整理すると,$d/(s+2)\leq t_2-t_2\leq d/s$ ということになります(ただし $s=0$ のときは右辺を $\infty$ とする).

よってまず $1$ 番目の条件を無視すると,dp の遷移は線分との Minkowski 和によって表せます.

dp 関数は常に上凸になり,

  • 平行移動
  • 線分との Minkowski 和(ある傾きをある長さ分だけ挿入する)
  • $y<0$ の部分の削除($y<0$ である間手前から大きな傾きの線分を削除)

という操作で管理できます.傾きとその長さを priority queue で持てばすべてできます.

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