B - Three Sequences 解説
by
hirayuu_At
ヒント:https://atcoder.jp/contests/arc211/editorial/14503
\(X=Y\) のとき
\(\max(\max(S_1),\max(S_2),\max(S_3))=0\) が達成可能です。
- \(S_1\):\(X\) 個の \(0\) からなる数列
- \(S_2\):\(Z\) 個の \(0\) からなる数列
- \(S_3\):\(Z\) 個の \(0\) からなる数列
が条件を満たします。明らかに長さの制約も満たしています。
\(X\lt Y\) のとき
長さを適当に調節して観察すると、\(\max(\max(S_1),\max(S_2),\max(S_3))=0\) は達成不可であることがわかります。
\(\max(\max(S_1),\max(S_2),\max(S_3))=1\) は常に達成可能です。これは複数の方法で構築できます。\(2\) つの解法を示しますが、どちらの場合も長さの制約を満たしていることは容易に確認できます。
writer解
- \(S_1\):\(X\) 個の \(1\) と \(Y\) 個の \(0\) をこの順につなげた数列
- \(S_2\):\(Z\) 個の \(1\) からなる数列
- \(S_3\):\(Y\) 個の \(0\) と \(Z\) 個の \(1\) をこの順につなげた数列
が条件を満たします。
admin/tester解
- \(S_1\):\(X\) 個の \(0\) と \(Y-X\) 個の \(1\) をこの順につなげた数列
- \(S_2\):\(Z\) 個の \(0\) からなる数列
- \(S_3\):\(Z\) 個の \(0\) と \(Y-X\) 個の \(1\) をこの順につなげた数列
が条件を満たします。(この解法だと、\(X=Y\) の場合分けがいらなくて楽かもしれません。微々たる差ですが。)
実装例 (Python (Codon 0.19.3), 27ms)
X, Y, Z = [int(i) for i in input().split()]
if X == Y:
print(X, " ".join(["0"] * X))
print(Z, " ".join(["0"] * Z))
print(Z, " ".join(["0"] * Z))
else:
print(X + Y, " ".join(["1"] * X + ["0"] * Y))
print(Z, " ".join(["1"] * Z))
print(Y + Z, " ".join(["0"] * Y + ["1"] * Z))
Bonus!: 出力できる数列の長さの最大値を \(X\) とします。出力形式が正しいとき、\(O(X^2)\) の計算量で確実に正しい判定結果を返す出力判定器を作りましょう。
Bonus! の解説
文字列 \(S\) と文字列 \(T\) があるときに、共通する連続部分列の長さの最大値を求める問題を \(3\) 回解きます。
\(DP[i][j]\) を、「\(S\) の \(i\) 文字目以降と \(T\) の \(j\) 文字目以降から、一致する文字数」とします。これは \(j\) の逆順、\(j\) が同じなら \(i\) の逆順、に更新できます。これらの最大値が求める値です。空間計算量は \(O(X^2)\) です。
また、両方の始点を全探索して、\(1\) 文字前が一致していないときのみ愚直に最大値を求める、としても同じ計算量が達成できることが証明できます。この場合は空間計算量 \(O(X)\) で済みます。
実際の出力判定器では、(なぜか指摘されるまで上記の解法に気づいていなかったので)片方の端を全探索してZ Algorithm(リンク先はsnukeさんのブログ)を使っています。定数倍が若干悪いですが、これでも空間計算量 \(O(X)\) を達成できます。Z Algorithmはとても面白いアルゴリズムです。
投稿日時:
最終更新:
