AtCoder Beginner Contest 218 参戦記
解けた問題数に不満はないが、解くのが遅いなあという感想.
ABC218A - Weather Forecast
1分半で突破. 書くだけ.
N = int(input())
S = input()
if S[N - 1] == 'o':
print('Yes')
else:
print('No')
ABC218B - qwerty
3分で突破. ASCII コードと文字の変換ができれば余裕でしょう.
P = map(int, open(0).read().split())
print(*(chr(ord('a') + p - 1) for p in P), sep='')
ABC218D - Rectangles
29分半で突破. (x0, y0) と (x0, y1) に呼応する点は (x1, y0), (x1, y1) なので、ある x0 に対して存在する y の集合と x1 に対して存在する y の集合の積集合の大きさを n とすると、nC2 の組み合わせが作れる. 後はすべての x0 と x1 の組み合わせに対してそれを求めて合計すれば答えが出る. 回答時は無駄に座標圧縮をして時間を溶かしてしまった.
N = int(input())
xy = [tuple(map(int, input().split())) for _ in range(N)]
d = {}
for x, y in xy:
d.setdefault(x, set())
d[x].add(y)
t = list(d.values())
result = 0
for i in range(len(t)):
for j in range(i + 1, len(t)):
n = len(t[i] & t[j])
result += n * (n - 1) // 2
print(result)
ABC218C - Shapes
26分半で突破. ぱっと見面倒くさいなあと思ったが、それほどでもなかった. 先頭と末尾の空行を削除するトリム関数と右90度回転する回転関数を作って、SとTをトリムして、SとTを回転してトリムする. これで平行移動については考えなくてよくなったので、Tを回転しながらSと一致するかを4回判定する、ただそれだけだった.
N = int(input())
S = [input() for _ in range(N)]
T = [input() for _ in range(N)]
def trim(a):
while a[0] == '.' * len(a[0]):
a = a[1:]
while a[-1] == '.' * len(a[-1]):
a = a[:-1]
return a
def rotate(a):
r = ['' for _ in range(len(a[0]))]
for i in range(len(a[0])):
for j in range(len(a) - 1, -1, -1):
r[i] += a[j][i]
return r
S = trim(S)
T = trim(T)
S = rotate(S)
T = rotate(T)
S = trim(S)
T = trim(T)
for i in range(4):
T = rotate(T)
if len(S) != len(T):
continue
if any(S[i] != T[i] for i in range(len(S))):
continue
print('Yes')
break
else:
print('No')
ABC218E - Destruction
17分半で突破. アルゴリズムを思いつくのに時間がかかり過ぎだった. この手の問題ではよくあるが、取り除くものを考えるのではなく、0から繋いでいくように考えると解ける. まずCiが負のものについては全て繋ぐ. 取り除く理由がまったくない. 後はCiが小さい方から順に必要があれば繋いでいく. 必要性の判断は辺の両端の頂点が既に別の辺経由で繋がっているかで判断できる. 判断は Union Find で簡単に実装できる.
from sys import setrecursionlimit, stdin
def find(parent, i):
t = parent[i]
if t < 0:
return i
t = find(parent, t)
parent[i] = t
return t
def unite(parent, i, j):
i = find(parent, i)
j = find(parent, j)
if i == j:
return
parent[j] += parent[i]
parent[i] = j
readline = stdin.readline
setrecursionlimit(10 ** 6)
N, M = map(int, readline().split())
ABC = [list(map(int, readline().split())) for _ in range(M)]
parent = [-1] * (N + 1)
result = 0
for a, b, c in sorted(ABC, key=lambda x: x[2]):
if c > 0 and find(parent, a) == find(parent, b):
result += c
continue
unite(parent, a, b)
print(result)
ABC218F - Blocked Roads
頂点1からNまで最短では多くてもたかだかN-1本の辺しか通らないので、そのN-1本についてだけ BFS で最短路計算しても TLE しないだろうと割とすぐ解き方は分かったのだが、残り10分では実装できないなと思って諦めた.