AtCoder Grand Contest 068 B問題メモ
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 を 1≤a1<a2<⋯<an≤L とする.
- T に含まれる 0 の index を 1≤b1<b2<⋯<bn≤L とする.
- 各 1≤i≤n に対し,頂点 ai と頂点 bi を結ぶ辺を g に追加する.
- S に含まれる 1 の個数を m とする.
- S に含まれる 1 の index を 1≤c1<c2<⋯<cm≤L とする.
- T に含まれる 1 の index を 1≤d1<d2<⋯<dm≤L とする.
- 各 1≤i≤m に対し,頂点 ci と頂点 di を結ぶ辺を g に追加する.
- 以上の手順で得た g を G(S,T) とする.
- 長さ N の整数列 A=(A1,A2,⋯,AN) が与えられます.
- 以下の条件をすべて満たす良い文字列組 (S,T) を 1 つ見つけてください.
- S の長さを L とする.N≤L≤105 である.
- 各 1≤i,j≤N について,G(S,T) で頂点 i と頂点 j が同じ連結成分に属すとき,そしてそのときのみ Ai=Aj である.
- なお,この問題の制約下で解が必ず存在することが証明できます.
制約
- 1≤N≤100
- 1≤Ai≤N
- 入力される値はすべて整数
解法
問題文は長いが、丁寧に定義を書いているためなので、理解はしやすい。
S,T の中の、0だけで 1,2,... 番目に出てきた同士、1だけで 1,2,... 番目に出てきた同士の
indexと同じ番号の頂点を結んだグラフで、先頭 N 頂点の連結・非連結関係を目的のものにする問題。
構築するグラフの頂点数 L は N よりかなり大きくても良い。
N+1 以降でいろいろ頑張ってもいいよ、ということ。
実験
最終的な構築方法とは少し異なるものの、まずは実際に先頭から S,T を A に矛盾しないように決めてみる。
1手1手に説明を挟むと冗長になるが、まぁ、言葉より実例を見た方が早いので。。。
実験して、「連結にしてはいけない頂点を連結にしない」ための制約が結構厳しいことがわかった。
一度 Ai=2 である位置の Si に“0”を置くと、次に T に“0”を置けるのは Aj=2 である位置しかないので、それ以外はずっと“1”を置き続けるしかない、みたいな箇所が多い。
だが、実験により、以下の傾向が見つかった。
- 実験の構築方法では、S は、i≥N+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”を使って W~Z の間を連結にする。
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 となり、余裕を持って L≤105 となる。