#include <algorithm>
#include <bitset>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

#define rep(i, n) for (int64_t i = 0; i < (int64_t)(n); i++)
#define irep(i, n) for (int64_t i = 0; i <= (int64_t)(n); i++)
#define rrep(i, n) for (int64_t i = (n)-1; i >= 0; i--)
#define rirep(i, n) for (int64_t i = n; i >= 0; i--)

#define chmax(a, b) (a) = max(a, b)
#define chmin(a, b) (a) = min(a, b)

int main() {
  int N;
  cin >> N;

  using D = tuple<int, int, int>;
  vector<D> data;
  rep(i, N) {
    int x, y;
    char d;
    cin >> x >> y >> d;

    int dir = 0;
    if (d == 'D' || d == 'U') {
      dir |= 2;
    }
    if (d == 'D' || d == 'L') {
      dir |= 1;
    }
    data.push_back(D(x, y, dir));
  }

  constexpr int INF = numeric_limits<int>::max();
  int result = INF;

  constexpr int MAX = 200'000;
  vector<vector<vector<int>>> tbl(4, vector<vector<int>>(MAX + 1));
  vector<vector<vector<int>>> cross(4, vector<vector<int>>(2 * MAX + 1)),
      cross2(4, vector<vector<int>>(2 * MAX + 1));
  rep(i, N) {
    int x, y, d;
    tie(x, y, d) = data[i];

    tbl[d][((d & 2) ? x : y)].push_back((d & 2) ? y : x);
    cross[d][x + y].push_back(x - y + MAX);
    cross2[d][x - y + MAX].push_back(x + y);
  }
  rep(i, 4) irep(j, MAX) { sort(tbl[i][j].begin(), tbl[i][j].end()); }

  rep(i, 4) irep(j, 2 * MAX) {
    sort(cross[i][j].begin(), cross[i][j].end());
    sort(cross2[i][j].begin(), cross2[i][j].end());
  }

  rep(i, 2) {
    irep(j, MAX) {
      for (int v : tbl[i << 1][j]) {
        const auto &tmp = tbl[(i << 1) ^ 1][j];
        auto iter = lower_bound(tmp.begin(), tmp.end(), v);
        if (iter != tmp.end()) {
          // cerr << i << " " << j << " " << v << " " << *iter << "\n";
          chmin(result, 5 * (*iter - v));
        }
      }
    }
  }

  rep(i, 2) {
    irep(j, 2 * MAX) {
      for (int v : cross[i][j]) {
        const auto &tmp = cross[i ^ 2][j];
        auto iter = lower_bound(tmp.begin(), tmp.end(), v);
        if (i == 0) {
          if (iter != tmp.end()) {
            cerr << i << " " << j << " " << v << " " << *iter << "\n";
            chmin(result, 5 * (*iter - v));
          }
        } else {
          if (iter != tmp.begin()) {
            chmin(result, 5 * (v - *prev(iter)));
          }
        }
      }
    }
  }

  rep(i, 2) {
    irep(j, 2 * MAX) {
      for (int v : cross2[i][j]) {
        const auto &tmp = cross2[i ^ 3][j];
        auto iter = lower_bound(tmp.begin(), tmp.end(), v);
        if (i == 0) {
          if (iter != tmp.end()) {
            chmin(result, 5 * (*iter - v));
          }
        } else {
          if (iter != tmp.begin()) {
            chmin(result, 5 * (v - *prev(iter)));
          }
        }
      }
    }
  }

  if (result == INF) {
    cout << "SAFE" << endl;
  } else {
    cout << result << endl;
  }
  return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<numeric>
#include<functional>
#include<algorithm>
#include<bitset>
#include<tuple>
#include<unordered_set>
#include<unordered_map>
#include<random>
#include<array>
#include<cassert>
using namespace std;
#define INF ((1<<25)-1)
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(v) v.begin(),v.end()


int N;
int X[200000];
int Y[200000];
char U[200000];


int dir(char c) {
	return c == 'U' ? 0 : c == 'R' ? 1 : c == 'D' ? 2 : 3;
}

int near(int v, const set<int> &s) {
	int ret = INF;
	auto it = s.lower_bound(v);
	if (it != s.end()) {
		ret = min(ret, *it - v);
	}

	return ret;
}


int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);


	int ans = INF;

	cin >> N;
	rep(i, N)cin >> X[i] >> Y[i] >> U[i];


	{
		unordered_map<int, array<set<int>, 4>> d;
		rep(i, N) {
			int a = X[i];
			d[a][dir(U[i])].insert(Y[i]);
		}
		// U, D
		for (const auto& p : d) {
			const auto& layer = p.second;
			for (int y : layer[dir('U')]) {

				ans = min(ans, near(y, layer[dir('D')]) * 5);
 			}
		}
	}
	{
		unordered_map<int, array<set<int>, 4>> d;
		rep(i, N) {
			int a = Y[i];
			d[a][dir(U[i])].insert(X[i]);
		}
		// L, R
		for (const auto& p : d) {
			const auto& layer = p.second;
			for (int y : layer[dir('R')]) {
				ans = min(ans, near(y, layer[dir('L')]) * 5);
			}
		}
	}


	{
		unordered_map<int, array<set<int>, 4>> d;
		rep(i, N) {
			int a = X[i] + Y[i];
			d[a][dir(U[i])].insert(Y[i]);
		}

		// R, U
		for (const auto& p : d) {
			const auto& layer = p.second;
			for (int y : layer[dir('U')]) {
				ans = min(ans, near(y, layer[dir('R')]) * 10);
			}
		}
		// D, L
		for (const auto& p : d) {
			const auto& layer = p.second;
			for (int y : layer[dir('L')]) {
				ans = min(ans, near(y, layer[dir('D')]) * 10);
			}
		}
	}
	

	{
		unordered_map<int, array<set<int>, 4>> d;
		rep(i, N) {
			int a = X[i] - Y[i] + 200000;
			d[a][dir(U[i])].insert(Y[i]);
		}

		// L, U
		for (const auto& p : d) {
			const auto& layer = p.second;
			for (int y : layer[dir('U')]) {
				ans = min(ans, near(y, layer[dir('L')]) * 10);
			}
		}
		// D, R
		for (const auto& p : d) {
			const auto& layer = p.second;
			for (int y : layer[dir('R')]) {
				ans = min(ans, near(y, layer[dir('D')]) * 10);
			}
		}
	}

	if (ans == INF)cout << "SAFE" << endl;
	else cout << ans << endl;

	return 0;
}
