
【ABC346】緑コーダーの競プロ参加記録 #8.5
その日のうちに記事を投稿することに挑戦してみます。
今回は解説というより感想です。
AtCoder Beginner Contest 346。使用言語はPythonです。
A問題 - Adjacent Product
コンテスト中の提出
https://atcoder.jp/contests/abc346/submissions/51546007
問題文にそのまま従いました。
""""""
N = int(input())
A = list(map(int, input().split()))
B = []
for i in range(N - 1):
B.append(A[i] * A[i + 1])
print(*B)
B問題 - Piano
コンテスト中の提出
https://atcoder.jp/contests/abc346/submissions/51551602
むずかしいです。
よく分からないので、'wbwbwwbwbwbw' を適当に100個くらい連結して、長さ$${W + B}$$の区間を全探索しました。
公式解説を読んではじめて mod の発想に気付く。
""""""
from collections import Counter
W, B = map(int, input().split())
S = 'wbwbwwbwbwbw' * 100
N = len(S)
ans = 'No'
for i in range(N - (W + B)):
t = S[i : i + (W + B)]
cnt = Counter(t)
if cnt['w'] == W and cnt['b'] == B:
ans = 'Yes'
break
print(ans)

C問題 - Σ
コンテスト中の提出
https://atcoder.jp/contests/abc346/submissions/51555790
「$${A}$$の中に一度も現れない数」を全探索するのは$${O(K)}$$となり 2 sec に間に合いません。
「$${1}$$から$${K}$$までの総和」を求める公式があり$${O(1)}$$で求められるので、「$${A}$$に含まれる整数」を引けばいいのかなという流れ。
""""""
N, K = map(int, input().split())
A = set(map(int, input().split()))
ans = K * (K + 1) // 2
ans -= sum(a for a in A if a <= K)
print(ans)

D問題 - Gomamayo Sequence
コンテスト中の提出
https://atcoder.jp/contests/abc346/submissions/51571298
「良い文字列」の条件は「$${i}$$文字目と$${i + 1}$$文字目が一致するようなものがちょうど$${1}$$つ存在する。」とのことなので、これを全探索するのかなというところからスタート。
そうすると、$${S_iS_{i+1}}$$を '00' にするのか '11' にするのかで2パターン考えられます。
また '1' と '0' を交互に並べるとき、端っこの1文字が決まれば文字列は一意に決まります。
よって、$${S_i}$$を含む左側と、$${S_{i+1}}$$を含む右側それぞれについて「1' と '0' が交互に並ぶ文字列」にするためのコストが分かればよさそう。

「隣り合う文字が異なる」ことと「$${S_i}$$の文字を変えるときにコスト$${C_i}$$がかかる」ことを考えてDPの遷移とします。

""""""
N = int(input())
S = "#" + input()
C = [0] + list(map(int, input().split()))
L = [[0] * 2 for _ in range(N + 2)]
R = [[0] * 2 for _ in range(N + 2)]
for i in range(1, N + 1):
if S[i] == '0':
L[i][0] = L[i - 1][1]
L[i][1] = L[i - 1][0] + C[i]
else:
L[i][0] = L[i - 1][1] + C[i]
L[i][1] = L[i - 1][0]
for i in reversed(range(1, N + 1)):
if S[i] == '0':
R[i][0] = R[i + 1][1]
R[i][1] = R[i + 1][0] + C[i]
else:
R[i][0] = R[i + 1][1] + C[i]
R[i][1] = R[i + 1][0]
ans = 1 << 60
for i in range(1, N):
ans = min(ans, L[i][0] + R[i + 1][0])
ans = min(ans, L[i][1] + R[i + 1][1])
print(ans)
E問題 - Paint
コンテスト中の提出
https://atcoder.jp/contests/abc346/submissions/51590178
ふつうにやると、上書きされる色の管理が大変。
発想を逆転して、操作を後ろの方から進めていくとします。
そうすると「上書き」ではなく「塗られてないマスのみを塗る」という挙動になります。
つまり、これまでに塗られた列の数を$${c}$$とすると、ある行を塗るときその色の個数は$${W - c}$$個増えます。列を塗るときも同様です。

はじめ全てのマスが色$${0}$$で塗られているのが地味にめんどくさいですね。
"""
逆から見ていく
"""
H, W, M = map(int, input().split())
Query = [tuple(map(int, input().split())) for _ in range(M)]
r, c = 0, 0
p = 2 * (10 ** 5)
Color = [0] * (p + 1)
used_R = [0] * (p + 1)
used_C = [0] * (p + 1)
other = H * W
for i in reversed(range(M)):
t, a, x = Query[i]
if t == 1:
if not used_R[a]:
used_R[a] = True
r += 1
Color[x] += W - c
other -= W - c
else:
if not used_C[a]:
used_C[a] = True
c += 1
Color[x] += H - r
other -= H - r
Color[0] += other
ans = []
for i in range(p + 1):
if Color[i] == 0:
continue
ans.append((i, Color[i]))
print(len(ans))
for a in ans:
print(*a)
F問題 - SSttrriinngg in StringString
upsolve
https://atcoder.jp/contests/abc346/submissions/51639021
解けなかったけど方針は合ってた! 嬉しいような悔しいような。

from string import ascii_lowercase
from bisect import bisect_right
def invalid(S, T):
ss = set(S)
tt = set(T)
for c in ascii_lowercase:
if not c in ss and c in tt:
return True
return False
def solve(x):
cnt = 1
curr = -1
for t in T:
""" 現在位置 curr 以降にある最初の文字 c は何個目? """
c = ord(t) - ord('a')
j = bisect_right(A[c], curr)
""" x 個の文字 c を使うために文字列 S をいくつ追加する? """
k = len(A[c])
p = min(x, k - j) # 文字列 S を追加せずに使える分
q = max(0, x - p) // k # 文字列 S を追加する個数
r = max(0, x - p) % k # まだ足りない分
if j + p + r - 1 >= k:
q += 1
j = (j + p + r - 1) % k
""" パラメータの更新 """
cnt += q
curr = A[c][j]
if cnt > N:
return False
return cnt <= N
N = int(input())
S = input()
T = input()
if invalid(S, T):
print(0)
exit()
A = [[] for _ in range(26)]
for i, s in enumerate(S):
c = ord(s) - ord('a')
A[c].append(i)
ok, ng = 0, 1 << 60
while ng - ok > 1:
mid = (ok + ng) // 2
if solve(mid):
ok = mid
else:
ng = mid
print(ok)
あとがき
その日のうちに記事を作るのは、たいへん!
従来の記事はたぶん後日あがります。あがらないかもしれません。
普段はこれよりボリュームのある解説記事を書いています。
こちらもよろしくお願いします。