Upgrade to Pro — share decks privately, control downloads, hide ads and more …

yukicoder 446 editorial

seekworser
September 13, 2024
110

yukicoder 446 editorial

seekworser

September 13, 2024
Tweet

Transcript

  1. ◼ Milk ★1: AC 100人 ◼ Minahoshi (Easy) ★1.5: AC

    99人 ◼ Mamehinata ★2: AC 71人 ◼ Chiffon ★2.5: AC 65人 ◼ Rusk ★2.5: AC 23人 ◼ Mint ★3: AC 44人 ◼ Lime and Karin ★4: AC 18人 ◼ Minahoshi (Hard) ★4: AC 3人 問題セット
  2. 解法 ◼ BFS木(BFS tree)というものがある ◼ グラフについてBFSで通る辺だけ残したグラフは木になる ◼ 根からの最短距離が d の頂点には、

    必ず根からの最短距離が d-1 の頂点から辺が 張られている ◼ 元のグラフにおいて、BFS木の深さが 2 以上 異なる頂点同士を結ぶ辺は無い
  3. 解法 ◼ BFS木(BFS tree)というものがある ◼ グラフについてBFSで通る辺だけ残したグラフは木になる ◼ 根からの最短距離が d の頂点には、

    必ず根からの最短距離が d-1 の頂点から辺が 張られている ◼ 元のグラフにおいて、BFS木の深さが 2 以上 異なる頂点同士を結ぶ辺は無い → 今塗られている深さの頂点に対して、 → 深さの差が1となる深さの頂点が → すべて塗られる 時刻 1:深さ 1 時刻 2:深さ 0, 2 時刻 3:深さ 1, 3, 5 ◼ あらかじめBFSで各頂点の深さを計算しておけば O(N+M) で解くことができる
  4. 問題概要 A B B B C C C C B

    B B A A 1回めのトースター 2回めのトースター ◼ あり得るすべての焼き方について、美味しさの総和の最大値を求める
  5. 解法 ◼ 切れ目の位置を1つ固定した問題は O(K log N) で解ける ◼ 切れ目の位置の候補は O(N)

    なので、全体で O(NK log N) となって間に合わない…… 本当か?
  6. 解法 ◼ 切れ目の位置を1つ固定した問題は O(K log N) で解ける ◼ 切れ目の位置の候補は O(N)

    なので、全体で O(NK log N) となって間に合わない…… 本当か? ◼ いちごは全部で K 個あるので、いちご同士の間隔であって、あいだの長さが 2N/K 以下であるような箇所が 必ず 1 箇所以上存在する。 ◼ いちご同士の間隔にはすべて切れ目をいれるので、その間隔にある切れ目候補だけ全探索すれば良い O(N/K * K log N) = O(N log N)で解くことができる
  7. 問題概要 ◼ 制約が10の12乗……? → N or M の ½ 乗の解法が怪しそう

    ◼ k が小さいところは愚直に計算するとして、kが大きいところで効率的に計算できないか考えたい
  8. 問題概要 ◼ 制約が10の12乗……? → N or M の ½ 乗の解法が怪しそう

    ◼ k が小さいところは愚直に計算するとして、kが大きいところで効率的に計算できないか考えたい ◼ M = k*d + r (r < k)として表したとき、M mod k (= r)は M – k*d のように表せる ◼ k が大きいとき、dとして考えられる値の候補は少ない ◼ 具体的には、k ≧ √M のとき、d の候補は √M 以下の値しか存在しない ◼ d を固定した場合の問題については等差数列の和の形になるので、d ごとに O(1) で計算可能 k < √M と k ≧ √Mで場合分けをして、k が大きい場合は d の値に応じて解くことによって O(√M) で計算可能
  9. 余談 ◼ 実装が結構めんどう(おなじところを重複して数えないようにするなど工夫が必要)なのでこの位置に ◼ 制約メタ読みで解法自体はかなり生えやすいと思う ◼ 直近の yukicoder 445 (菁々祭プログラミングコンテスト2024)

    でかなり近い問題が出されたけど、 一応解説にこちらの想定解はなかったので強行…… ◼ Mintの想定解のNとMを入れ替えて、x=1,2,…,N について解くことで、O(N√N) で解けるはず…
  10. 解法 2 3 1 4 5 ◼ 頂点 1 を通るパスであって、条件を満たすものを考える

    ◼ さらに、①頂点1を端点とするもの ②頂点1が端点でないもの に分けると、①の方は簡単に求めること ができる(頂点1から開始してDFSをすれば良い)
  11. 2 3 1 4 5 ◼ 頂点 1 を通るパスであって、②頂点1が端点でないもの ◼

    ライムの木を1、カリンの木を-1として、頂点1からの距離を指数とする多項式を各部分木ごとに考える ある部分木から別の部分木に行く方法で条件を満たすもの f1 = x f2 = x^-2 + x^-1 + 1 解法
  12. 2 3 1 4 5 ◼ 頂点 1 を通るパスであって、②頂点1が端点でないもの ◼

    ライムの木を1、カリンの木を-1として、頂点1からの距離を指数とする多項式を各部分木ごとに考える ある部分木から別の部分木に行く方法で条件を満たすもの f1 = x f2 = x^-2 + x^-1 + 1 = ∑_{k=-1,0,1,…} [x^k] f1 f2 解法
  13. ◼ 部分木が 3 つ以上だったら? ◼ 「異なる部分木同士の多項式の積の総和」は O(N log N) で計算できる

    ◼ tatyam さんのスライドが詳しい https://speakerdeck.com/tatyam_prime/gao-nan-yi- du-mu-wen-ti-wojie-kutekunitukuji 解法
  14. ◼ 頂点 x を含むパスについての解が木の頂点数 N に対して O(N log N) で求まる

    木を重心分解して再帰的に解くことで全体 O(N log^2 N) で解くことができる 解法
  15. 余談 ◼ ★4 の 2 問のうちかなりストレートな典型枠 ◼ 解法としては LC の

    Frequency Table of Tree Distance と基本的に同じ ◼ 負の冪を扱う必要がある部分が少し違うくらい ◼ 実装がまじで苦しい、大変だった、みんなも苦しんでほしい
  16. 解法 ◼ とりあえず実験してみる N=2: ab N=3: abb N=4: aabb N=5:

    bbaab N=6: abbaaa N=7: bbaaaba N=8: bbaaabab N=9: baaababbb N=10: bbbaaababb N=11: aababbbaaaa 総和 0 総和 1 総和 2 総和 3 総和 5 総和 7 総和 9 総和 11 総和 13 総和 16
  17. ◼ とりあえず実験してみる N=2: ab N=3: abb N=4: aabb N=5: bbaab

    N=6: abbaaa N=7: bbaaaba N=8: bbaaabab N=9: baaababbb N=10: bbbaaababb N=11: aababbbaaaa 総和 0 総和 1 総和 2 総和 3 総和 5 総和 7 総和 9 総和 11 総和 13 総和 16 +1 +1 +1 +2 +2 +2 +2 +2 +3 解法
  18. ◼ とりあえず実験してみる ◼ 総和の隣接差分が増えるタイミングでは何が起きている? N=2: ab N=3: abb N=4: aabb

    N=5: bbaab N=6: abbaaa N=7: bbaaaba N=8: bbaaabab N=9: baaababbb N=10: bbbaaababb N=11: aababbbaaaa 総和 0 総和 1 総和 2 総和 3 総和 5 総和 7 総和 9 総和 11 総和 13 総和 16 +1 +1 +1 +2 +2 +2 +2 +2 +3 解法
  19. ◼ とりあえず実験してみる ◼ 総和の隣接差分が増えるタイミングでは何が起きている? N=2: ab N=5: bbaab N=10: bbbaaababb

    →長さ1の連続部分列にa,bが一度ずつ →長さ2の連続部分列にaa,ab,ba,bbが一度ずつ →長さ3の連続部分列にaaa,aab,aba,abb,baa,bba,bab,bbb →が一度ずつ なるべく異なる連続部分列を文字列中に含めたい 解法
  20. aaa aab aba abb baa bab bba bbb 1 2

    3 4 5 6 7 8 頂点番号 対応する文字列 接続可能な頂点 1, 2 3, 4 5, 6 7, 8 1, 2 3, 4 5, 6 7, 8 ◼ 長さ k の文字列を頂点として、各頂点の末尾の k−1 文字が、隣接する頂点の先頭 k−1 文字と一致す るように辺を張った有向グラフを考える i=1,…,2^{k-1}について ⌊x/2⌋ = i となるような頂点を全て通り、 指定された長さとなるパスを1つ構築する 解法
  21. aaa aab aba abb baa bab bba bbb 1 2

    3 4 5 6 7 8 頂点番号 対応する文字列 接続可能な頂点 1, 2 3, 4 5, 6 7, 8 1, 2 3, 4 5, 6 7, 8 ◼ 長さ k の文字列を頂点として、各頂点の末尾の k−1 文字が、隣接する頂点の先頭 k−1 文字と一致す るように辺を張った有向グラフを考える ◼ 長さ 2^{k-1}+1 で、[1と2のいずれか][3と4のいずれか]…[7と8のいずれか]の頂点を全て通り、始点と 終点が一致するウォークが1つ取れたとする。このとき使用した頂点をすべて削除する →残るグラフは、各頂点の入次数と出次数が1となるグラフであり、いくつかのサイクルに分割できる →サイクルの始点と終点で、元のサイクルと行き先をswapすることでサイクルの長さを徐々に大きくできる (詳しい操作は解説を見てください……) 解法
  22. aaa aab aba abb baa bab bba bbb 1 2

    3 4 5 6 7 8 頂点番号 対応する文字列 接続可能な頂点 1, 2 3, 4 5, 6 7, 8 1, 2 3, 4 5, 6 7, 8 ◼ 長さ k の文字列を頂点として、各頂点の末尾の k−1 文字が、隣接する頂点の先頭 k−1 文字と一致す るように辺を張った有向グラフを考える ◼ 長さ 2^{k-1}+1 で、[1と2のいずれか][3と4のいずれか]…[7と8のいずれか]の頂点を全て通り、始点と 終点が一致するウォークが1つ取れたとする。このとき使用した頂点をすべて削除する →残るグラフは、各頂点の入次数と出次数が1となるグラフであり、いくつかのサイクルに分割できる →サイクルの始点と終点で、元のサイクルと行き先をswapすることでサイクルの長さを徐々に大きくできる (詳しい操作は解説を見てください……) どうやって? 解法