/ 最近 .rdf 追記 編集 設定 本棚

log[20200709] AtCoder Beginner Contest 173F 問題 Intervals on Tree



20200709() コンテト時間中に F 問題が解けたことはまだない時間をかけさえすれば解けるということでもなく解けた問題だけが日記になっているのだ

最終更: 2020-08-15T20:50+0900

[AtCoder] AtCoder Beginner Contest 173F 問題 Intervals on Tree

コンテト中に解けなかった(問題文を読むところまでいかなかった)問題に挑戦

「連結成分っていうのがわかんないよねず。出力例1の解説を読むに頂点集合が辺で繋がれたいくつの部分に分かれるかを数えるみたい

 考えたこと

  1. 頂点集合は考え得るすべての通し番号から作られる(1~21~32~7など)頂点番号と木の構造に関連はない
  2. 頂点集合ごとに Union-Find するのはどう考えても間に合わない
  3. LCA が高速に求められたらいけるだろう頂点集合に含まれる任意の2頂点をすべて試していたらどう考えても間に合わない
  4. トポロジカルソトして割り振った番号と実際の頂点番号を見比べて何かわかるだろうわかんない
  5. 木を構成する頂点決まったやり方で並べていったら(20200607p01.02)連結成分が配列の連続する部分として見出せるだろうそんなにうまくない
  6. ってどこが根とか決まってたっけ? どのドでも根になれる? 葉でも根になる? なる
  7. 一番考えやすいのは葉が単独で連結成分を構成するときCと親Pのあいだに辺があるような(=CPが共に頂点集合に含まれるよう) L,R の選び方が L<=[C,P].min && [C,P].max<=R だからその否定(記:これは嘘実装中に気がついたがこれだと頂点 C が頂点集合に含まれないケースが紛れてい)
  8. 大元の根(※勝手に1つ決めます)に一番近いドに連結成分を代表させることにするとあるCを根とする連結成分がカウトされるかどうかはCと親とのあいだに辺があるかどうかでわかる
  9. すべての連結成分(=任意のドを根とする連結成分)についてそれがカウトされるような L,R の選び方を数えよう

 提出 #15106396 (AC / 307 Byte / 351 ms / 35716 KB)

スクリト化にあたって一番考えたのって重複組合せの求め方だった最初 N×N にして間違っていて仕切りを置く場所を考えるんだったようなと思い出すのに時間がかかったそして最終的に補集合ではなく目的のものを直接数えられることがわかって無駄になった

あとょこざいなやり方だとは思うけどCP の大小で場合分けをしたくないなと思って符号を利用した>[(c+1)*(p-c),(p-c)*(c-N),].maxカンマが余分これ2頂点間の最短パスは短絡辺を通るか通らないかのどちらかであるが最後まで見抜けなかった恨みである

こうしたら最後の計算で根(c==0)の場合を例外扱いしないで済む

11
P[0] = N # 0 を根にする。N は計算のため。
21
22
23
24
p (0...N).sum{|c|
	p = P[c]
	[(c+1)*(p-c),(p-c)*(c-N)].max
}

 Ruby(2.7)によるすべての提出

ワンライナーとかわけがわかりません><

これ? 閉路が存在しないなら「連結成分の個数 = 頂点数 - 辺の数が成り立つ 木のどの部分を切り取っても木だろうし木なら頂点数と辺の数は NN-1 に決まってるので頂点数と辺の数のずれの大きさがそのまま森を構成する木(連結成分)の数というのはまあ言われたらそうかもねという感じ

言われなきゃわからないしなんなら連結なグラフで頂点数と辺の数の比が NN-1 ならそれは木だというのも最初からなんだか化かされてるような気がしてる