#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <set>
#include <map>
#include <vector>
#include <string>

#include <cmath>
#include <queue>
#include <stack>

using namespace std;

#define LL long long

const int dx[4] = {1, -1, 0, 0};
const int dy[4] = {0, 0, 1, -1};

LL mod(LL x, LL md) {
	return ((x % md) + md) % md;
}

class Mint {
public:
	static LL md;
	LL x;
	Mint(LL _x = 0) {
		x = mod(_x, md);
	}
	Mint(const Mint &y) {
		x = mod(y.x, md);
	}
};

void MintMyExgcd(LL a, LL b, LL &x, LL &y) {
	// solve equation ax + by = 1 (mod m)
	LL md = Mint::md;
	if (b == 0) {
		y = 0;
		x = 1;
		return ;
	}
	MintMyExgcd(b, a % b, x, y);
	LL t = y;
	y = mod(x - (a / b) * y, md);
	x = t;
}

LL MintNY(LL x) {
	if (x == 0) {
		return 1;
	}
	LL md = Mint::md;
	LL a, b;
	MintMyExgcd(x, md, a, b);
	while (a < 0) {
		a += md;
	}
	return a;
}

/* LL gcd(LL a, LL b) {
	if (b == 0) {
		return a;
	}
	return gcd(b, a % b);
} */

Mint operator+(Mint a, Mint b) {
	return Mint(mod(a.x + b.x, Mint::md));
}
Mint operator-(Mint a, Mint b) {
	return Mint(mod(a.x - b.x, Mint::md));
}
Mint operator*(Mint a, Mint b) {
	return Mint(mod(a.x * b.x, Mint::md));
}
Mint operator/(Mint a, Mint b) {
	Mint c = Mint(MintNY(b.x));
	return Mint(mod(a.x * c.x, Mint::md));
}

Mint operator-(Mint a) {
	return Mint(-a.x);
}
bool operator==(Mint a, Mint b) {
	return a.x == b.x;
}
bool operator!=(Mint a, Mint b) {
	return a.x != b.x;
}
bool operator>(Mint a, Mint b) {
	return a.x > b.x;
}
bool operator<(Mint a, Mint b) {
	return a.x < b.x;
}
bool operator>=(Mint a, Mint b) {
	return a.x >= b.x;
}
bool operator<=(Mint a, Mint b) {
	return a.x <= b.x;
}

void operator+=(Mint &a, Mint b) {
	a = a + b;
}
void operator-=(Mint &a, Mint b) {
	a = a - b;
}
void operator*=(Mint &a, Mint b) {
	a = a * b;
}
void operator/=(Mint &a, Mint b) {
	a = a / b;
}

ostream& operator<<(ostream &out, Mint a) {
	out << a.x;
	return out;
}

istream& operator>>(istream &in, Mint &a) {
	in >> a.x;
	return in;
}

Mint factorial(LL n) {
	if (n == 0) {
		return Mint(1);
	}
	Mint res = 1;
	for (LL i = 1; i <= n; ++i) {
		res *= i;
	}
	return res;
}
Mint multiRange(LL s, LL t) {
	Mint res = 1;
	for (LL i = s; i <= t; ++i) {
		res *= i;
	}
	return res;
}

Mint getC(LL n, LL k) {
	if (n - k < k) {
		return getC(n, n - k);
	}
	return multiRange(n - k + 1, n) / factorial(k);
}

Mint getA(LL n, LL k) {
	return multiRange(n - k + 1, n);
}

Mint countNonNegativeDivision(LL n, LL k) {
	return getC(n + k - 1, k - 1);
}
Mint countPositiveDivision(LL n, LL k) {
	if (n < k) {
		return 0;
	}
	if (k <= 0) {
		return 0;
	}
	return getC(n - 1, k - 1);
}
Mint quickMod(Mint a, LL b) {
	Mint res = 1;
	while (b > 0) {
		if (b % 2) {
			res *= a;
		}
		a *= a;
		b /= 2;
	}
	return res;
}
template<class TypeName>
vector<TypeName> getVector1D(int n, TypeName val) {
    return vector<TypeName>(n, val);
}
template<class TypeName>
vector<vector<TypeName> > getVector2D(int n1, int n2, TypeName val) {
    vector<vector<TypeName> > res(n1);
    for (int i = 0; i < n1; ++i) {
        res[i] = vector<TypeName>(n2, val);
    }
    return res;
}
template<class TypeName>
vector<vector<vector<TypeName> > > getVector3D(int n1, int n2, int n3, TypeName val) {
    vector<vector<vector<TypeName> > > res(n1);
    for (int i = 0; i < n1; ++i) {
        res[i] = vector<vector<TypeName> >(n2);
        for (int j = 0; j < n2; ++j) {
            res[i][j] = vector<TypeName>(n3, val);
        }
    }
    return res;
}
template<class TypeName>
vector<vector<vector<vector<TypeName> > > > getVector4D(int n1, int n2, int n3, int n4, TypeName val) {
    vector<vector<vector<vector<TypeName> > > > res(n1);
    for (int i = 0; i < n1; ++i) {
        res[i] = vector<vector<vector<TypeName> > >(n2);
        for (int j = 0; j < n2; ++j) {
            res[i][j] = vector<vector<TypeName> >(n3);
            for (int k = 0; k < n3; ++k) {
                res[i][j][k] = vector<TypeName>(n4, val);
            }
        }
    }
    return res;
}

LL Mint::md = 1000000007;

vector<int> x, y;
vector<char> d;
int n;

char getDirect() {
	char c = getchar();
	while (c < 'A' || c > 'Z') {
		c = getchar();
	}
	return c;
}

void updateMax(int &a, int b) {
	a = max(a, b);
}
void updateMin(int &a, int b) {
	a = min(a, b);
}
int inf = 10000000;
int getMinTime(vector<int> &tp, vector<int> &tm) {
	sort(tp.begin(), tp.end());
	sort(tm.begin(), tm.end());
	int res = inf + 10;
	int cur = 0;
	for (int i = 0; i < tp.size(); ++i) {
		while (cur < tm.size() && tm[cur] < tp[i]) {
			++cur;
		}
		if (cur < tm.size()) {
			updateMin(res, (tm[cur] - tp[i]) * 5);
		}
	}
	return res;
}

bool coll = false;
int minTime = inf;

void updateRes(int tm) {
	if (tm < minTime) {
		coll = true;
		minTime = tm;
	}
}

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


	scanf("%d", &n);
	x.clear(); y.clear(); d.clear();
	int xx, yy;
	int xMax = 0, yMax = 0;
	char dd;
	for (int i = 0; i < n; ++i) {
		scanf("%d%d", &xx, &yy);
		xMax = max(xMax, xx);
		yMax = max(yMax, yy);
		dd = getDirect();
		x.push_back(xx); y.push_back(yy);
		d.push_back(dd);
	}

	// deal with LR
	// vector<int> toRXMin(yMax + 1, inf), toRXMax(yMax + 1, -1);
	// vector<int> toLXMin(yMax + 1, inf), toLXMax(yMax + 1, -1);
	// for (int i = 0; i < n; ++i) {
	// 	if (d[i] == 'L') {
	// 		updateMax(toLXMax[y[i]], x[i]);
	// 		updateMin(toLXMin[y[i]], x[i]);
	// 	} else if (d[i] == 'R') {
	// 		updateMax(toRXMax[y[i]], x[i]);
	// 		updateMin(toRXMin[y[i]], x[i]);
	// 	}
	// }
	// for (int i = 0; i <= yMax; ++i) {
	// 	if (toLXMax[i] >= toRXMin[i]) {
	// 		coll = true;
	// 		updateMin(minTime, toLX)
	// 	}
	// }
	vector<vector<int> > toLX(yMax + 1), toRX(yMax + 1);
	vector<vector<int> > toUY(xMax + 1), toDY(xMax + 1);
	for (int i = 0; i <= xMax; ++i) {
		toUY[i].clear(); toDY[i].clear();
	}
	for (int i = 0; i <= yMax; ++i) {
		toLX[i].clear(); toRX[i].clear();
	}
	for (int i = 0; i < n; ++i) {
		if (d[i] == 'L') {
			toLX[y[i]].push_back(x[i]);
		}
		if (d[i] == 'R') {
			toRX[y[i]].push_back(x[i]);
		}
		if (d[i] == 'U') {
			toUY[x[i]].push_back(y[i]);
		}
		if (d[i] == 'D') {
			toDY[x[i]].push_back(y[i]);
		}
	}
	for (int i = 0; i <= xMax; ++i) {
		updateRes(getMinTime(toUY[i], toDY[i]));
	}
	for (int i = 0; i <= yMax; ++i) {
		updateRes(getMinTime(toRX[i], toLX[i]));
	}

	// finish LR and UD

	// deal with RU and LD
	int maxSum = xMax + yMax;
	vector<vector<int> > xR(maxSum + 1), xU(maxSum + 1), xL(maxSum + 1), xD(maxSum + 1);
	for (int i = 0; i < xR.size(); ++i) {
		xR[i].clear(); xL[i].clear();
		xU[i].clear(); xD[i].clear();
	}
	for (int i = 0; i < n; ++i) {
		if (d[i] == 'L') {
			xL[x[i] + y[i]].push_back(x[i]);
		}
		if (d[i] == 'R') {
			xR[x[i] + y[i]].push_back(x[i]);
		}
		if (d[i] == 'U') {
			xU[x[i] + y[i]].push_back(x[i]);
		}
		if (d[i] == 'D') {
			xD[x[i] + y[i]].push_back(x[i]);
		}
	}
	for (int i = 0; i < xL.size(); ++i) {
		updateRes(getMinTime(xR[i], xU[i]) * 2);
		updateRes(getMinTime(xD[i], xL[i]) * 2);
	}

	// vector<vector<int> > xR(maxSum + 1), xU(maxSum + 1), xL(maxSum + 1), xD(maxSum + 1);
	for (int i = 0; i < xR.size(); ++i) {
		xR[i].clear(); xL[i].clear();
		xU[i].clear(); xD[i].clear();
	}
	for (int i = 0; i < n; ++i) {
		if (d[i] == 'L') {
			xL[x[i] - y[i] + yMax].push_back(x[i]);
		}
		if (d[i] == 'R') {
			xR[x[i] - y[i] + yMax].push_back(x[i]);
		}
		if (d[i] == 'U') {
			xU[x[i] - y[i] + yMax].push_back(x[i]);
		}
		if (d[i] == 'D') {
			xD[x[i] - y[i] + yMax].push_back(x[i]);
		}
	}
	for (int i = 0; i < xL.size(); ++i) {
		updateRes(getMinTime(xU[i], xL[i]) * 2);
		updateRes(getMinTime(xR[i], xD[i]) * 2);
	}

	if (coll) {
		cout << minTime << endl;
	} else {
		cout << "SAFE" << endl;
	}

	return 0;
}

Measured memory_bytes: 79900