ABC399をPythonで（A～D）

AtCoder Beginner Contest 399の解答等の速報的まとめ

https://atcoder.jp/contests/abc399



# A問題
https://atcoder.jp/contests/abc399/tasks/abc399_a

違う個所を数える
```python:A
n = int(input())
s = input()
t = input()

print(sum(s_i != t_i for s_i, t_i in zip(s, t)))
```

# B問題
https://atcoder.jp/contests/abc399/tasks/abc399_b

各点数ごとに何位になるか求めてから答えを出力する
```python:B
n = int(input())
p = list(map(int, input().split()))

r = 1
data = sorted(p)
rank = dict()
while data:
    x = data.pop()
    rank[x] = r

    k = 1
    while data and data[-1] == x:
        data.pop()
        k += 1
    r += k

for p_i in p:
    print(rank[p_i])
```

# C問題
https://atcoder.jp/contests/abc399/tasks/abc399_c

UnionFindで、すでに連結な頂点を繋げる辺の数を数える
```python:C
from collections import defaultdict
import sys;sys.setrecursionlimit(10 ** 6)

class UnionFind:
    """
    URL : https://note.nkmk.me/python-union-find/
    """
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        group_members = defaultdict(list)
        for member in range(self.n):
            group_members[self.find(member)].append(member)
        return group_members

    def __str__(self):
        return '\n'.join(f'{r}: {m}' for r, m in self.all_group_members().items())


n, m = map(int, input().split())
UF = UnionFind(n)
ans = 0
for _ in range(m):
    u, v = map(lambda x:int(x) - 1, input().split())
    if UF.same(u, v):
        ans += 1
    else:
        UF.union(u, v)

print(ans)
```

# D問題
https://atcoder.jp/contests/abc399/tasks/abc399_d

数$a_1,a_2,b_1,b_2$について、$a_1$と$b_1$,$a_2$と$b_2$が隣接しているか調べる
```python:D
def get_para(A, ind):
    res = set()
    if ind > 0:
        res.add(A[ind - 1])
    if ind + 1 < len(A):
        res.add(A[ind + 1])

    return res


for _ in range(int(input())):
    n = int(input())
    a = list(map(lambda x:int(x) - 1, input().split()))

    ng = set()
    for a_i, a_j in zip(a, a[1:]):
        if a_i == a_j:
            ng.add(a_i)

    d = dict()
    for i, a_i in enumerate(a):
        if a_i not in d:
            d[a_i] = list()
        else:
            a[i] += n
        d[a_i].append(i)

    ans = set()
    for key, val in d.items():
        if key in ng:
            continue

        first, second = val
        f = get_para(a, first)
        s = get_para(a, second)
        while f:
            target = f.pop()
            if target not in s and (target - n in s or target + n in s) and target not in ng:
                ans.add(tuple(sorted([key, target])))

    print(len(ans))
```

# E問題
https://atcoder.jp/contests/abc399/tasks/abc399_e

文字ごとのパスに変換して、変換がいうまくいくか調べる
うまくいくためには
- 一つの文字が複数の文字に変換しない
- ループがあるときは使っていない文字に変換できるか調べる

と思って計算したがWAまみれ