#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
template <class T>
using ordered_set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
template <class T>
using ordered_multiset = __gnu_pbds::tree<T, __gnu_pbds::null_type, less_equal<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;

#define PI atan2(0, -1)
#define EPS 1e-9
#define INF 5e18
#define MOD 1000000007

#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound

int N, ret = MOD;
vector<pair<int, int>> U, R, D, L;

void checkUR(){
    map<int, set<int>> ups;
    for(auto lol : U) ups[lol.f+lol.s].insert(lol.f);
    for(auto lol : R){
        int x = lol.f, y = lol.s;
        if(ups.find(x+y) == ups.end()) continue;
        auto it = ups[x+y].lb(x);
        if(it != ups[x+y].end()) {
            ret = min(ret, ((*it-x)*10));
        }
    }
}

void checkUL(){
    map<int, set<int>> lefts;
    for(auto lol : L) lefts[lol.f-lol.s].insert(lol.f);
    for(auto lol : U){
        int x = lol.f, y = lol.s;
        if(lefts.find(x-y) == lefts.end()) continue;
        auto it = lefts[x-y].lb(x);
        if(it != lefts[x-y].end()) {
            ret = min(ret, ((*it-x)*10));
        }
    }
}

void checkDR(){
    map<int, set<int>> downs;
    for(auto lol : D) downs[lol.f-lol.s].insert(lol.f);
    for(auto lol : R){
        int x = lol.f, y = lol.s;
        if(downs.find(x-y) == downs.end()) continue;
        auto it = downs[x-y].lb(x);
        if(it != downs[x-y].end()) {
            ret = min(ret, ((*it-x)*10));
        }
    }
}

void checkDL(){
    map<int, set<int>> lefts;
    for(auto lol : L) lefts[lol.f+lol.s].insert(lol.f);
    for(auto lol : D){
        int x = lol.f, y = lol.s;
        if(lefts.find(x+y) == lefts.end()) continue;
        auto it = lefts[x+y].lb(x);
        if(it != lefts[x+y].end()) {
            ret = min(ret, ((*it-x)*10));
        }
    }
}

void checkUD(){
    map<int, set<int>> downs;
    for(auto lol : D) downs[lol.f].insert(lol.s);
    for(auto lol : U){
        int x = lol.f, y = lol.s;
        if(downs.find(x) == downs.end()) continue;
        auto it = downs[x].lb(y);
        if(it != downs[x].end()){
            ret = min(ret, ((*it-y)*5));
        }
    }
}

void checkRL(){
    map<int, set<int>> lefts;
    for(auto lol : L) lefts[lol.s].insert(lol.f);
    for(auto lol : R){
        int x = lol.f, y = lol.s;
        if(lefts.find(y) == lefts.end()) continue;
        auto it = lefts[y].lb(x);
        if(it != lefts[y].end()){
            ret = min(ret, ((*it-x)*5));
        }
    }
}

int main(){
    //freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
    ios_base::sync_with_stdio(0); cin.tie(0); cout << fixed << setprecision(10);
    cin >> N;
    for(int i = 0; i < N; i++){
        int x, y; char d; cin >> x >> y >> d;
        if(d == 'U') U.pb({x, y});
        if(d == 'R') R.pb({x, y});
        if(d == 'D') D.pb({x, y});
        if(d == 'L') L.pb({x, y});
    }
    checkUR();
    checkUL();
    checkDR();
    checkDL();
    checkUD();
    checkRL();
    if(ret == MOD) cout << "SAFE\n";
    else cout << ret << '\n';
    return 0;
}

/******************************
Kateba ii dake no hanashi darou
Success is only a victory away
- No Game No Life Opening
******************************/

Measured memory_bytes: 32324