#include <bits/stdc++.h>
#include <ext/hash_map>
#include <ext/numeric>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

#define REP(i,n) for( (i)=0 ; (i)<(n) ; (i)++ )
#define rep(i,x,n) for( (i)=(x) ; (i)<(n) ; (i)++ )
#define REV(i,n) for( (i)=(n) ; (i)>=0 ; (i)-- )
#define FORIT(it,x) for( (it)=(x).begin() ; (it)!=(x).end() ; (it)++ )
#define foreach(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();++it)
#define rforeach(it,c) for(__typeof((c).rbegin()) it=(c).rbegin();it!=(c).rend();++it)
#define foreach2d(i, j, v) foreach(i,v) foreach(j,*i)
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define SZ(x) ((int)(x).size())
#define MMS(x,n) memset(x,n,sizeof(x))
#define mms(x,n,s) memset(x,n,sizeof(x)*s)
#define pb push_back
#define mp make_pair
#define NX next_permutation
#define UN(x) sort(all(x)),x.erase(unique(all(x)),x.end())
#define CV(x,n) count(all(x),(n))
#define FIND(x,n) find(all(x),(n))-(x).begin()
#define ACC(x) accumulate(all(x),0)
#define PPC(x) __builtin_popcountll(x)
#define LZ(x) __builtin_clz(x)
#define TZ(x) __builtin_ctz(x)
#define mxe(x) *max_element(all(x))
#define mne(x) *min_element(all(x))
#define low(x,i) lower_bound(all(x),i)
#define upp(x,i) upper_bound(all(x),i)
#define NXPOW2(x) (1ll << ((int)log2(x)+1))
#define PR(x) cout << #x << " = " << (x) << endl ;

typedef unsigned long long ull;
typedef long long ll;
typedef vector<int> vi;
typedef vector<vector<int> > vvi;
typedef pair<int, int> pii;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

const int OO = (int) 2e9;
const double eps = 1e-9;

const int N = 2e5 + 5;

int n;
int x[N], y[N];
char u[N];
unordered_map<char, unordered_map<int, set<int>>> row, col, digp, digm;

int main() {
	std::ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
#ifndef ONLINE_JUDGE
//	freopen("in.txt", "rt", stdin);
//	freopen("out.txt", "wt", stdout);
#endif
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> x[i] >> y[i] >> u[i];
		if (u[i] == 'R' || u[i] == 'L') {
			row[u[i]][y[i]].insert(x[i]);
		} else {
			col[u[i]][x[i]].insert(y[i]);
			digp[u[i]][x[i] + y[i]].insert(x[i]);
			digm[u[i]][x[i] - y[i]].insert(x[i]);
		}
	}
	int res = INT_MAX;
	for (int i = 0; i < n; i++) {
		if (u[i] == 'R') {
			auto it = row['L'][y[i]].upper_bound(x[i]);
			if (it != row['L'][y[i]].end()) {
				res = min(res, (*it - x[i]) * 5);
			}
			it = digm['D'][x[i] - y[i]].upper_bound(x[i]);
			if (it != digm['D'][x[i] - y[i]].end()) {
				res = min(res, (*it - x[i]) * 10);
			}
			it = digp['U'][x[i] + y[i]].upper_bound(x[i]);
			if (it != digp['U'][x[i] + y[i]].end()) {
				res = min(res, (*it - x[i]) * 10);
			}
		} else if (u[i] == 'L') {
			auto it = digm['U'][x[i] - y[i]].lower_bound(x[i]);
			if (it != digm['U'][x[i] - y[i]].begin()) {
				it--;
				res = min(res, (x[i] - *it) * 10);
			}
			it = digp['D'][x[i] + y[i]].lower_bound(x[i]);
			if (it != digp['D'][x[i] + y[i]].begin()) {
				it--;
				res = min(res, (x[i] - *it) * 10);
			}
		} else if (u[i] == 'U') {
			auto it = col['D'][x[i]].upper_bound(y[i]);
			if (it != col['D'][x[i]].end()) {
				res = min(res, (*it - y[i]) * 5);
			}
		}
	}
	if (res == INT_MAX)
		cout << "SAFE\n";
	else
		cout << res << endl;
	return 0;
}


Measured memory_bytes: 85076