Codeforces Round 507

スポンサーリンク

A. Timetable

難読.

$(i,j)$ が good なのは,次が成り立つ場合です:$a$ から $a_i$,$b$ から $b_j$ を削除してインデックスをつけなおしたとき $a_k+t\leq b_k$.

各 $(i,x_i)$ が valid になるという条件から,各 $b_j$ の下限が求まります.$b$ は下限を満たし単調増加になるようなもののうちで最小にとっておき,$(i,x_i+1)$ が invalid になるかどうかをチェックします.

B. Subway Pursuit

ジャッジの動きが決定的であることを使う必要があります.

現在の候補区間が大きいならば二分探索,ある程度小さいならば $l=r$ であるような質問をして当たり待ち.としました.

C. Network Safety

$x$ を固定すると,現時点での端点の xor がちょうど $x$ であるような辺について条件が発生し,$A$ の数え上げはそのような条件による連結成分数によって書けます.辺のある頂点だけについて unionfind を作る,あるいはリセット可能な unionfind を使うなどすれば計算できます.

D. You Are Given a Tree

答を $f(k)$ とすると, $k$ を決めたときのそれは木 dp で計算できます.各 subtree の根では,「子から来ているものを $2$ つ組み合わせてパスを作る」「パスは作らずに最も長いパスを残す」の $2$ 択があって,前者を優先して選ぶ貪欲をすればよいです.

$f$ の値の種類数は $O(\sqrt{N})$ 通りしかありません.$kf(k)\leq N$ から $k\geq \sqrt{N}$ に対する値の種類数が $O(\sqrt{N})$ 通りだからです.

よってすべての境界を二分探索で求めることで,$f(k)$ の計算を $O(\sqrt{N}\log N)$ 回やればよくなります.

E. Summer Oenothera Exhibition

$O((N+Q)\sqrt{N}\log N)$ 時間だと思います.

クエリをひとつとった場合の解法は次のような形です:$i$ から $f(i)$ に辺を張る($i<f(i)$).頂点 $N$ を根とする根付き木になる.頂点 $0$ の深さを求めよ.

この辺を link cut tree で管理します.クエリは適当にソートして順に処理します.

辺はクエリのたびにたくさん変更されるはずですが,必要な変更だけを検出して変更するようにします.つまり,

「頂点 $0$ から $N$ までのパス上の辺で変更が必要なもののうち,頂点 $0$ に最も近いもの検出.それを張り替える.」

という操作を繰り返します.各ノードに親をいつ変える必要かの値を持たせておけば,検出はパス上の二分探索になります.実装は link cut tree で目的のパスを expose してしまえば普通に平衡二分木と同じです.

実装はそれだけです.計算量解析について考えます.

  • 変更したあとの辺の長さ($f(i)-i$)が $\sqrt{N}$ 以下:始点ごとに数えると $N\sqrt{N}$ 回以下.
  • 変更したあとの長さが $\sqrt{N}$ より大きい:クエリごとに数えると $Q\sqrt{N}$ 回以下.

となるので,上述の工程を $O((N+Q)\sqrt{N})$ 回で解けるということになります.

このワーストケースが作れるのかは分かりませんでした.解説にもいくつかの解法がありますが,よほど不思議な解法がない限りはこの解法で $f(i)$ の計算回数は最小化されていると思います.

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