AtCoder Grand Contest 068 B問題メモ
1個の問題をひたすら時間かけてじっくり考えられるのは、AGCでしかできない体験。(高レート帯で鎬を削っている人は別だが)
B - 01 Graph Construction
問題文
- 0,1 のみからなる文字列の組 $(S,T)$ が次の条件をすべて満たすとき (そしてそのときのみ) それを良い文字列組と呼ぶことにします.
- 条件
- $S,T$ に含まれる 0 の個数は等しい.
- $S,T$ に含まれる 1 の個数は等しい.
- 特に,良い文字列組 $(S,T)$ について,$S,T$ の長さは同じです.
- 良い文字列組 $(S,T)$ に対し,無向グラフ $G(S,T)$ を次のように定義します.
- $S$ の長さを $L$ とする.頂点 $1,2,\cdots,L$ からなるグラフ $g$ をつくる.
- $S$ に含まれる 0 の個数を $n$ とする.
- $S$ に含まれる 0 の index を $1 \leq a_1 \lt a_2 \lt \cdots \lt a_n \leq L$ とする.
- $T$ に含まれる 0 の index を $1 \leq b_1 \lt b_2 \lt \cdots \lt b_n \leq L$ とする.
- 各 $1 \leq i \leq n$ に対し,頂点 $a_i$ と頂点 $b_i$ を結ぶ辺を $g$ に追加する.
- $S$ に含まれる 1 の個数を $m$ とする.
- $S$ に含まれる 1 の index を $1 \leq c_1 \lt c_2 \lt \cdots \lt c_m \leq L$ とする.
- $T$ に含まれる 1 の index を $1 \leq d_1 \lt d_2 \lt \cdots \lt d_m \leq L$ とする.
- 各 $1 \leq i \leq m$ に対し,頂点 $c_i$ と頂点 $d_i$ を結ぶ辺を $g$ に追加する.
- 以上の手順で得た $g$ を $G(S,T)$ とする.
- 長さ $N$ の整数列 $A=(A_1,A_2,\cdots,A_N)$ が与えられます.
- 以下の条件をすべて満たす良い文字列組 $(S,T)$ を $1$ つ見つけてください.
- $S$ の長さを $L$ とする.$N \leq L \leq 10^5$ である.
- 各 $1 \leq i,j \leq N$ について,$G(S,T)$ で頂点 $i$ と頂点 $j$ が同じ連結成分に属すとき,そしてそのときのみ $A_i=A_j$ である.
- なお,この問題の制約下で解が必ず存在することが証明できます.
制約
- $1 \leq N \leq 100$
- $1 \leq A_i \leq N$
- 入力される値はすべて整数
解法
問題文は長いが、丁寧に定義を書いているためなので、理解はしやすい。
$S,T$ の中の、0だけで $1,2,...$ 番目に出てきた同士、1だけで $1,2,...$ 番目に出てきた同士の
indexと同じ番号の頂点を結んだグラフで、先頭 $N$ 頂点の連結・非連結関係を目的のものにする問題。
構築するグラフの頂点数 $L$ は $N$ よりかなり大きくても良い。
$N+1$ 以降でいろいろ頑張ってもいいよ、ということ。
実験
最終的な構築方法とは少し異なるものの、まずは実際に先頭から $S,T$ を $A$ に矛盾しないように決めてみる。
1手1手に説明を挟むと冗長になるが、まぁ、言葉より実例を見た方が早いので。。。
実験して、「連結にしてはいけない頂点を連結にしない」ための制約が結構厳しいことがわかった。
一度 $A_i=2$ である位置の $S_i$ に“0”を置くと、次に $T$ に“0”を置けるのは $A_j=2$ である位置しかないので、それ以外はずっと“1”を置き続けるしかない、みたいな箇所が多い。
だが、実験により、以下の傾向が見つかった。
- 実験の構築方法では、$S$ は、$i \ge N+1$ の範囲では全て1が置かれる
- その際、$N$ 番目以降は $A$ がいくつか除かれつつ繰り返される
$L$ の上限は、$N^2$ より大きく余裕があることと合わせ、次の構築方法が思いつく。
構築
$S$ を、「先頭 $N$ 個を“0”、それより後を全て“1”」とする。
$T$ の側は、ほぼ“1”を置くことを基本としつつ、所々に計 $N$ 個の“0”を置く。
1周に付き1個、$T$ 側に“0”を置くことを考える。
$A_i=x$ が出現するindexを順に $I(x)=(i_1,i_2,...,i_k)$ とすると、次のように構築する。
- $l$ 周目では、「$I(A_l)$ で $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$ の中で $A_i=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=\frac{N(N+1)}{2}$ となり、余裕を持って $L \le 10^5$ となる。