AtCoder Grand Contest 068 B問題メモ

AtCoder Grand Contest 068

1個の問題をひたすら時間かけてじっくり考えられるのは、AGCでしかできない体験。(高レート帯で鎬を削っている人は別だが)

B - 01 Graph Construction

問題文

  • 0,1 のみからなる文字列の組 (S,T)(S,T) が次の条件をすべて満たすとき (そしてそのときのみ) それを良い文字列組と呼ぶことにします.
    • 条件
      • S,T に含まれる 0 の個数は等しい.
      • S,T に含まれる 1 の個数は等しい.
    • 特に,良い文字列組 (S,T) について,S,T の長さは同じです.
  • 良い文字列組 (S,T) に対し,無向グラフ G(S,T) を次のように定義します.
    • S の長さを L とする.頂点 1,2,,L からなるグラフ g をつくる.
    • S に含まれる 0 の個数を n とする.
      • S に含まれる 0 の index を 1a1<a2<<anL とする.
      • T に含まれる 0 の index を 1b1<b2<<bnL とする.
      • 1in に対し,頂点 ai と頂点 bi を結ぶ辺を g に追加する.
    • S に含まれる 1 の個数を m とする.
      • S に含まれる 1 の index を 1c1<c2<<cmL とする.
      • T に含まれる 1 の index を 1d1<d2<<dmL とする.
      • 1im に対し,頂点 ci と頂点 di を結ぶ辺を g に追加する.
    • 以上の手順で得た gG(S,T) とする.
  • 長さ N の整数列 A=(A1,A2,,AN) が与えられます.
  • 以下の条件をすべて満たす良い文字列組 (S,T)1 つ見つけてください.
    • S の長さを L とする.NL105 である.
    • 1i,jN について,G(S,T) で頂点 i と頂点 j が同じ連結成分に属すとき,そしてそのときのみ Ai=Aj である.
  • なお,この問題の制約下で解が必ず存在することが証明できます.

制約

  • 1N100
  • 1AiN
  • 入力される値はすべて整数

解法

問題文は長いが、丁寧に定義を書いているためなので、理解はしやすい。
S,T の中の、0だけで 1,2,... 番目に出てきた同士、1だけで 1,2,... 番目に出てきた同士の indexと同じ番号の頂点を結んだグラフで、先頭 N 頂点の連結・非連結関係を目的のものにする問題。

構築するグラフの頂点数 LN よりかなり大きくても良い。
N+1 以降でいろいろ頑張ってもいいよ、ということ。

実験

最終的な構築方法とは少し異なるものの、まずは実際に先頭から S,TA に矛盾しないように決めてみる。

1手1手に説明を挟むと冗長になるが、まぁ、言葉より実例を見た方が早いので。。。

長いので折りたたみ

実験して、「連結にしてはいけない頂点を連結にしない」ための制約が結構厳しいことがわかった。
一度 Ai=2 である位置の Si に“0”を置くと、次に T に“0”を置けるのは Aj=2 である位置しかないので、それ以外はずっと“1”を置き続けるしかない、みたいな箇所が多い。

だが、実験により、以下の傾向が見つかった。

  • 実験の構築方法では、S は、iN+1 の範囲では全て1が置かれる
  • その際、N 番目以降は A がいくつか除かれつつ繰り返される

L の上限は、N2 より大きく余裕があることと合わせ、次の構築方法が思いつく。

構築

S を、「先頭 N 個を“0”、それより後を全て“1”」とする。
T の側は、ほぼ“1”を置くことを基本としつつ、所々に計 N 個の“0”を置く。

1周に付き1個、T 側に“0”を置くことを考える。

Ai=x が出現するindexを順に I(x)=(i1,i2,...,ik) とすると、次のように構築する。

  • l 周目では、「I(Al)l の次に出てくるindex(最後の場合は先頭)」に相当する頂点の T に“0”を置く

「1周」「相当する頂点」などの言葉の定義が曖昧だが、言葉より図で示した方が速い。以下のようにする。

周          1                   2                 3               4             5
i: 1 2 3 4 5 6 7 8 910| ....             |                |              |            |
A: 1 2 3 4 2 5 4 2 6 2| 2 3 4 2 5 4 2 6 2| 2 3 4 5 4 2 6 2| 2 4 5 4 2 6 2| 2 4 5 2 6 2|...
S: 0 0 0 0 0 0 0 0 0 0| 1 1 1 1 1 1 1 1 1| 1 1 1 1 1 1 1 1| 1 1 1 1 1 1 1| 1 1 1 1 1 1|...
T: 0 1 1 1 1 1 1 1 1 1| 1 1 1 0 1 1 1 1 1| 1 0 1 1 1 1 1 1| 1 1 1 0 1 1 1| 1 1 1 0 1 1|...

T で“0”が置かれた箇所は、A に登場する数字の順になっていることがわかる。
また、T に“0”が置かれた数字は、A の次の周回では除かれている。

A に複数回出てくる“2”に注目すると、以下のようになっている。

  • “0”によって A の「1番目」の2(i=2)と結ばれているのは、2周目で「2番目」に出現する“2”
  • “0”によって A の「2番目」の2(i=5)と結ばれているのは、5周目で(元)「3番目」に出現する“2”
    • ※2番目に出現する“2”が3周目以降除かれているため実際は2番目に出現するが、由来としては3番目

もう少し詳しく見るため、A,S,T の中で Ai=2 に該当する箇所だけ取り出す。
1周目で出てくる順に W,X,Y,Z と記号を振ると、

周    1        2       3      4      5     6    7    8   9 10    
   W X Y Z  W X Y Z  W Y Z  W Y Z  W Y Z  W Z  W Z  W Z  W  W
A: 2 2 2 2| 2 2 2 2| 2 2 2| 2 2 2| 2 2 2| 2 2| 2 2| 2 2| 2| 2|
S: 0 0 0 0| 1 1 1 1| 1 1 1| 1 1 1| 1 1 1| 1 1| 1 1| 1 1| 1| 1|
T: 1 1 1 1| 1 0 1 1| 1 1 1| 1 1 1| 1 0 1| 1 1| 1 1| 1 0| 1| 0|
            a b c d  e f g  h i j  k l m  n o  p q  r s  t  u  ┐"1"により同じ文字で
   a b c d  e   f g  h i j  k l m  n   o  p q  r s  t    u     ┘示された箇所同士が結ばれる
   w x y z                                                     ┐"0"により同じ文字で
              w                      x                y     z  ┘示された箇所同士が結ばれる

“1”によって、1周目のWと2周目のW (a)、2周目のWと3周目のW (e)、3周目のWと4周目のW (h)、、、が連結になっていく。
要するに、W,X,Y,Z の記号が同じものは、全ての周を通して連結になる。
この上で、“0”を使って WZ の間を連結にする。

2周目の T 側に置いた“0”(w)で、1周目のWと2周目のXが結ばれる。
つまり、全てのWと全てのXが連結になる。

5周目の T 側の“0”(x)で、1周目のXと5周目のYが結ばれる。
8周目の T 側の“0”(y)で、1周目のYと8周目のZが結ばれることで、全てが連結になった。

10周目の T 側の“0”(z)で、1周目のZと10周目のWを結び閉じることで、 これ以降、余計な箇所と連結になることを防ぎ、完結する。

この構築方法は、L=N(N+1)2 となり、余裕を持って L105 となる。

Python3

programming_algorithm/contest_history/atcoder/2024/0929_agc068.txt · 最終更新: 2024/10/08 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0