#include <iostream>
#include <fstream>
#include <algorithm>
#include <iomanip>
#include <random>
#include <ctime>
#include <bitset>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <cstring>
#include <queue>
#include <deque>
#include <stack>
#include <climits>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define ld long double
#define ull unsigned long long
#define ll long long
#define pb push_back
#define pii pair<int, int>
#define pll pair<ll, ll>
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define fast_io cout.tie(0), cin.tie(0), ios_base::sync_with_stdio(0)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using namespace std;
//using namespace __gnu_pbds;
//typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
ld eps = (ld)1 / 1e6;
ll inf = LLONG_MAX, mod1 = 1e9 + 7, mod2 = 998244353;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }
ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
vector<pll> vu, vr, vd, vl;
set<pll> st;
map<ll, set<ll>> mxu, mxd, myl, myr;
map<ll, set<ll>> mdu, mdr, mdl, mdd;
map<ll, set<ll>> du, dr, dl, dd;

int main()
{
    fast_io;
    ll n, i, x, y, ans = inf;
    char ch;
    cin >> n;
    for (i = 1; i <= n; i++)
    {
        cin >> x >> y >> ch;
        if (st.find({x, y}) != st.end()) cout << 0, exit(0);
        if (ch == 'U') vu.pb({x, y}), mxu[x].insert(y), mdu[x + y].insert(y), du[x - y].insert(y);
        else if (ch == 'R') vr.pb({x, y}), myr[y].insert(x), mdr[x + y].insert(y), dr[x - y].insert(y);
        else if (ch == 'D') vd.pb({x, y}), mxd[x].insert(y), mdd[x + y].insert(y), dd[x - y].insert(y);
        else vl.pb({x, y}), myl[y].insert(x), mdl[x + y].insert(y), dl[x - y].insert(y);
        st.insert({x, y});
    }
    for (i = 0; i <= 200000; i++)
    {
        for (auto f: mxu[i])
        {
            auto g = mxd[i].upper_bound(f);
            if (g == mxd[i].end()) continue;
            ans = min(ans, 5 * (*g - f));
        }
        for (auto f: myr[i])
        {
            auto g = myl[i].upper_bound(f);
            if (g == myl[i].end()) continue;
            ans = min(ans, 5 * (*g - f));
        }
    }
    for (i = 0; i <= 400000; i++)
    {
        for (auto f: mdu[i])
        {
            auto g = mdr[i].upper_bound(f);
            if (g == mdr[i].end()) continue;
            ans = min(ans, 10 * (*g - f));
        }
        for (auto f: mdl[i])
        {
            auto g = mdd[i].upper_bound(f);
            if (g == mdd[i].end()) continue;
            ans = min(ans, 10 * (*g - f));
        }
    }
    for (i = -200000; i <= 200000; i++)
    {
        for (auto f: du[i])
        {
            auto g = dl[i].upper_bound(f);
            if (g == dl[i].end()) continue;
            ans = min(ans, 10 * (*g - f));
        }
        for (auto f: dr[i])
        {
            auto g = dd[i].upper_bound(f);
            if (g == dd[i].end()) continue;
            ans = min(ans, 10 * (*g - f));
        }
    }
    if (ans == inf) cout << "SAFE";
    else cout << ans;
    return 0;
}

Measured memory_bytes: 289608