Buggy python submission (verdict: Runtime Error):
from collections import deque, Counter, defaultdict
from itertools import chain, combinations
import json
# import numpy as np
import bisect
import sys
import math
import bisect
from functools import lru_cache
import itertools

sys.setrecursionlimit(10 ** 8)

M = 10 ** 9 + 7
INF = 10 ** 17


def main():
    N = int(input())
    XYU = [
        [a for a in input().split()]
        for _ in range(N)
    ]

    # N, K = [int(a) for a in input().split()]
    # A = [int(a) for a in input().split()]
    # T1, T2, T3 = [int(a) for a in input().split()]

    up = []
    down = []
    right = []
    left = []
    for xi, yi, ui in XYU:
        if ui == 'U':
            up.append((int(xi), int(yi)))
            continue
        if ui == 'D':
            down.append((int(xi), int(yi)))
            continue
        if ui == 'R':
            right.append((int(xi), int(yi)))
            continue
        if ui == 'L':
            left.append((int(xi), int(yi)))
            continue

    def a():
        conflict = 10 ** 50
        xtable = {}
        for xi, yi in down:
            if xi not in xtable:
                xtable[xi] = []
            ind = bisect.bisect_left(xtable[xi], yi)
            xtable[xi].insert(ind, yi)
        for xi, yi in up:
            if xi in xtable:
                ind = bisect.bisect_left(xtable[xi], yi)
                if ind != len(xtable[xi]):
                    conflict = min(conflict, (xtable[xi][ind] - yi) * 5)
        ytable = {}
        for xi, yi in left:
            if yi not in ytable:
                ytable[yi] = []
            ind = bisect.bisect_left(ytable[yi], xi)
            ytable[yi].insert(ind, xi)
        for xi, yi in right:
            if yi in ytable:
                ind = bisect.bisect_left(ytable[yi], xi)
                if ind != len(ytable[yi]):
                    conflict = min(conflict, (ytable[yi][ind] - xi) * 5)
        return conflict

    left_l1 = {}
    left_l2 = {}
    for xi, yi in left:
        v1 = yi - xi
        if v1 not in left_l1:
            left_l1[v1] = []
        ind = bisect.bisect_left(left_l1[v1], xi)
        left_l1[v1].insert(ind, xi)

        v2 = xi + yi
        if v2 not in left_l2:
            left_l2[v2] = []
        ind = bisect.bisect_left(left_l2[v2], xi)
        left_l2[v2].insert(ind, xi)

    right_l1 = {}
    right_l2 = {}
    for xi, yi in right:
        v1 = yi - xi
        if v1 not in right_l1:
            right_l1[v1] = []
        ind = bisect.bisect_left(right_l1[v1], xi)
        right_l1[v1].insert(ind, xi)

        v2 = xi + yi
        if v2 not in right_l2:
            right_l2[v2] = []
        ind = bisect.bisect_left(right_l2[v2], xi)
        right_l2[v2].insert(ind, xi)

    conflict = a()

    for xi, yi in up:
        v1 = yi - xi
        v2 = xi + yi
        if v1 in left_l1:
            l = left_l1[v1]
            ind = bisect.bisect_left(l, xi)
            if ind != len(l):
                xx = l[ind]
                conflict = min(conflict, abs(xx - xi) * 10)
        if v2 in right_l2:
            l = right_l2[v2]
            ind = bisect.bisect_right(l, xi)
            if ind != 0:
                xx = l[ind]
                conflict = min(conflict, abs(xx - xi) * 10)
    for xi, yi in down:
        v1 = yi - xi
        v2 = xi + yi
        if v1 in right_l1:
            l = right_l1[v1]
            ind = bisect.bisect_right(l, xi)
            if ind != 0:
                xx = l[ind]
                conflict = min(conflict, abs(xx - xi) * 10)
        if v2 in left_l2:
            l = left_l2[v2]
            ind = bisect.bisect_left(l, xi)
            if ind != len(l):
                xx = l[ind]
                conflict = min(conflict, abs(xx - xi) * 10)
    if conflict == 10**50:
        print('SAFE')
        return
    print(conflict)


if __name__ == "__main__":
    main()



Fixed submission:
from collections import deque, Counter, defaultdict
from itertools import chain, combinations
import json
# import numpy as np
import bisect
import sys
import math
import bisect
from functools import lru_cache
import itertools

sys.setrecursionlimit(10 ** 8)

M = 10 ** 9 + 7
INF = 10 ** 17


def main():
    N = int(input())
    XYU = [
        [a for a in input().split()]
        for _ in range(N)
    ]

    # N, K = [int(a) for a in input().split()]
    # A = [int(a) for a in input().split()]
    # T1, T2, T3 = [int(a) for a in input().split()]

    up = []
    down = []
    right = []
    left = []
    for xi, yi, ui in XYU:
        if ui == 'U':
            up.append((int(xi), int(yi)))
            continue
        if ui == 'D':
            down.append((int(xi), int(yi)))
            continue
        if ui == 'R':
            right.append((int(xi), int(yi)))
            continue
        if ui == 'L':
            left.append((int(xi), int(yi)))
            continue

    def a():
        conflict = 10 ** 50
        xtable = {}
        for xi, yi in down:
            if xi not in xtable:
                xtable[xi] = []
            ind = bisect.bisect_left(xtable[xi], yi)
            xtable[xi].insert(ind, yi)
        for xi, yi in up:
            if xi in xtable:
                ind = bisect.bisect_left(xtable[xi], yi)
                if ind != len(xtable[xi]):
                    conflict = min(conflict, (xtable[xi][ind] - yi) * 5)
        ytable = {}
        for xi, yi in left:
            if yi not in ytable:
                ytable[yi] = []
            ind = bisect.bisect_left(ytable[yi], xi)
            ytable[yi].insert(ind, xi)
        for xi, yi in right:
            if yi in ytable:
                ind = bisect.bisect_left(ytable[yi], xi)
                if ind != len(ytable[yi]):
                    conflict = min(conflict, (ytable[yi][ind] - xi) * 5)
        return conflict

    left_l1 = {}
    left_l2 = {}
    for xi, yi in left:
        v1 = yi - xi
        if v1 not in left_l1:
            left_l1[v1] = []
        ind = bisect.bisect_left(left_l1[v1], xi)
        left_l1[v1].insert(ind, xi)

        v2 = xi + yi
        if v2 not in left_l2:
            left_l2[v2] = []
        ind = bisect.bisect_left(left_l2[v2], xi)
        left_l2[v2].insert(ind, xi)

    right_l1 = {}
    right_l2 = {}
    for xi, yi in right:
        v1 = yi - xi
        if v1 not in right_l1:
            right_l1[v1] = []
        ind = bisect.bisect_left(right_l1[v1], xi)
        right_l1[v1].insert(ind, xi)

        v2 = xi + yi
        if v2 not in right_l2:
            right_l2[v2] = []
        ind = bisect.bisect_left(right_l2[v2], xi)
        right_l2[v2].insert(ind, xi)

    conflict = a()

    for xi, yi in up:
        v1 = yi - xi
        v2 = xi + yi
        if v1 in left_l1:
            l = left_l1[v1]
            ind = bisect.bisect_left(l, xi)
            if ind != len(l):
                xx = l[ind]
                conflict = min(conflict, abs(xx - xi) * 10)
        if v2 in right_l2:
            l = right_l2[v2]
            ind = bisect.bisect_right(l, xi)
            if ind != 0:
                xx = l[ind - 1]
                conflict = min(conflict, abs(xx - xi) * 10)
    for xi, yi in down:
        v1 = yi - xi
        v2 = xi + yi
        if v1 in right_l1:
            l = right_l1[v1]
            ind = bisect.bisect_right(l, xi)
            if ind != 0:
                xx = l[ind - 1]
                conflict = min(conflict, abs(xx - xi) * 10)
        if v2 in left_l2:
            l = left_l2[v2]
            ind = bisect.bisect_left(l, xi)
            if ind != len(l):
                xx = l[ind]
                conflict = min(conflict, abs(xx - xi) * 10)
    if conflict == 10 ** 50:
        print('SAFE')
        return
    print(conflict)


if __name__ == "__main__":
    main()