0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AtCoder Beginner Contest 218 参戦記

Last updated at Posted at 2021-09-11

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分では実装できないなと思って諦めた.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?