// Success consists of going from failure to failure without loss of enthusiasm
#include <bits/stdc++.h>
using namespace std;
#define nl '\n'
#define pb push_back
#define sz(x) int(x.size())
#define f first
#define s second
#define mp make_pair
using ll = long long;
using pl = pair<ll, ll>;
using pi = pair<int, int>;
template<class T> using V = vector<T>;
template<class T> using pq = priority_queue<T, vector<T>, greater<T>>;
using vi = V<int>;
using vl = V<ll>;
using vpl = V<pl>;
using vpi = V<pi>;
const int INF = 1e9 + 10;
struct T {
	array<int, 3> ans = {INF, -1, -1}; // time of crash
	int l = -INF, lx = -1; // ship coming from left (max)
	int r = INF, rx = -1; // ship coming from right (min)
};
struct Seg {
	T ID; 
	V<T> seg; int n; T cmb(T a, T b) {
		T c; c.ans = min(a.ans, b.ans);
		if (b.lx != -1) c.l = b.l, c.lx = b.lx;
		else c.l = a.l, c.lx = a.lx;
		if (a.rx != -1) c.r = a.r, c.rx = a.rx;
		else c.r = b.r, c.rx = b.rx;
		c.ans = min(a.ans, b.ans);
		if (b.r - a.l < c.ans[0]) c.ans = {b.r - a.l, a.lx, b.rx};
		return c;
	}
	void init(int _n) {
		for(n = 1; n < _n;) n *= 2;
		seg.assign(2 * n, ID);
	}
	void pull(int p) { seg[p] = cmb(seg[2 * p], seg[2 * p + 1]); }
	void upd(int p, T x) {
		seg[p += n] = x;
		for(p /= 2; p; p /= 2) pull(p);
	}
	array<int, 3> get() { return seg[1].ans; }
};
int main() {
	cin.tie(0)->sync_with_stdio(0);
	
	int N; cin >> N;
	vi X(N), Y(N); V<char> D(N);
	for(int i = 0; i < N; i++) {
		cin >> X[i] >> Y[i] >> D[i];
	}
	if (N <= 5000) {
		V<array<int, 3>> E;
		for(int i = 0; i < N; i++) {
			for(int j = 0; j < N; j++) {
				if (D[i] == D[j]) continue;
				if (D[i] == 'S' && D[j] == 'N') {
					if (X[i] == X[j] && Y[i] < Y[j]) {
						int t = Y[j] - Y[i];
						E.pb({t / 2, i, j});
					}
				} 
				if (D[i] == 'E' && D[j] == 'W') {
					if (Y[i] == Y[j] && X[i] < X[j]) {
						int t = X[j] - X[i];
						E.pb({t / 2, i, j});
					}
				}
				if (D[i] == 'S' && D[j] == 'W') {
					if (X[i] - Y[i] == X[j] - Y[j] && X[i] < X[j]) {
						int t = X[j] - X[i];
						E.pb({t, i, j});
					}
				}
				if (D[i] == 'N' && D[j] == 'E') {
					if (X[i] - Y[i] == X[j] - Y[j] && X[i] > X[j]) {
						int t = X[i] - X[j];
						E.pb({t, i, j});
					}
				}
				if (D[i] == 'N' && D[j] == 'W') {
					if (X[i] + Y[i] == X[j] + Y[j] && X[i] < X[j]) {
						int t = X[j] - X[i];
						E.pb({t, i, j});
					}
				}
				if (D[i] == 'S' && D[j] == 'E') {
					if (X[i] + Y[i] == X[j] + Y[j] && X[i] > X[j]) {
						int t = X[i] - X[j];
						E.pb({t, i, j});
					}
				}
			}
		}	
		sort(begin(E), end(E));
		vi dead(N, 0);
		for(int i = 0; i < sz(E); i++) {
			int j = i; vi upd;
			while(j < sz(E) && E[i][0] == E[j][0]) {
				auto [t, x, y] = E[j];
				// cout << t << " -> " << x << " " << y << endl;
				if (!dead[x] && !dead[y]) {
					upd.pb(x); upd.pb(y);
				}
				j++;
			}
			i = j - 1;
			for(auto& x : upd) dead[x] = 1;
		}
		
		for(int i = 0; i < N; i++) if (!dead[i]) cout << i + 1 << nl;
	} else {
		map<int, int> to;
		for(int i = 0; i < N; i++) to[X[i] + Y[i]]++;
		int M = 0; for(auto& [k, v] : to) v = M++;
		V<vpi> G(M);
		for(int i = 0; i < N; i++) {
			G[to[X[i] + Y[i]]].pb(mp(X[i], i));
		}
		V<Seg> st(M);
		pq<array<int, 3>> q;
		for(int i = 0; i < M; i++) {
			sort(begin(G[i]), end(G[i]));
			int n = sz(G[i]);
			st[i].init(n);
			for(int x = 0; x < n; x++) {
				if (D[G[i][x].s] == 'S') {
					st[i].upd(x, T{{INF, -1, -1}, -INF, -1, G[i][x].f, G[i][x].s});
				} else {
					st[i].upd(x, T{{INF, -1, -1}, G[i][x].f, G[i][x].s, INF, -1});
				}
			}
			// cout << i << endl;
			q.push(st[i].get());
		}
		auto rem = [&](int d, int x) {
			int pos = lower_bound(begin(G[d]), end(G[d]), mp(X[x], x)) - begin(G[d]);
			st[d].upd(pos, st[d].ID);
		};
		vi dead(N, INF);
		while(sz(q)) {
			auto [t, x, y] = q.top(); q.pop();
			if (t == INF) break;
			// cout << t << " " << x << " " << y << endl;
			if (dead[x] < t || dead[y] < t) continue;
			dead[x] = min(dead[x], t);
			dead[y] = min(dead[y], t);
			int d = to[X[x] + Y[x]];
			rem(d, x); rem(d, y);
			q.push(st[d].get());
		}
		for(int i = 0; i < N; i++) if (dead[i] == INF) cout << i + 1 << nl;
	}
	exit(0-0);
}
// Breathe In, Breathe Out
	
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |