Problem:
Problem B:
Vector Field
In 20015, JAG (Jagan Acceleration Group) has succeeded in inventing a new accelerator named
Force Point for an experiment of proton collision on the two-dimensional $xy$-plane. If a proton
touches a Force Point, it is accelerated to twice its speed and its movement direction is veered. A
proton may be veered by a Force Field in four ways: the positive or negative directions parallel
to the $x$- or the $y$-axis. The direction in which a proton veers is determined by the type of the
Force Point. A Force Point can accelerate a proton only once because the Force Point disappears
immediately after the acceleration. Generating many Force Points on the two-dimensional plane,
which is called a 2D Force Point Field, allows us to accelerate a proton up to a target speed by
sequentially accelerating the proton with the Force Points in the 2D Force Point Filed.
The Force Point generation method is still under experiment and JAG has the following technical
limitations:
JAG cannot generate a Force Point with a specified position and a type.
JAG cannot generate a Force Point after putting a proton into a 2D Force Point Field.
JAG cannot move Force Points.
JAG cannot change a protons direction except by the effect of Force Points.
JAG can use only one proton for a 2D Force Point Field.
JAG can put a proton moving in any direction with its speed 1 at any position in a 2D
Force Point Field.
In order to achieve the maximum speed of a proton, the engineers at JAG have to choose the
optimal initial position and the optimal initial direction of the proton so that the proton is
accelerated by as many Force Points as possible, after carefully observing the generated 2D
Force Point Field.
By observing a generated 2D Force Point Field, the number of the generated Force Points is
known to be $n$. The position ($x_i$, $y_i$) and the direction veering type $d_i$ of the $i$-th point are
also known. Your task is to write a program to calculate the maximum speed of a proton by
acceleration on a given 2D Force Point Field when JAG puts a proton optimally.
Input
The input consists of a single test case which describes a 2D Force Point Field in the following
format.
$n$
$x_1$ $y_1$ $d_1$
...
$x_n$ $y_n$ $d_n$
The first line contains one integer $n$ ($1 \leq n \leq 3,000$) which is the number of the Force Points on
the 2D Force Point Field. Each of the next $n$ lines contains two integers $x_i$ and $y_i$ ($|x_i|$, $|y_i| \leq 10^9$)
and one character $d_i$ ($d_i$ is one of '>', 'v', '<' or '^'). $x_i$ and $y_i$ represent a coordinate of the $i$-th
Force Point, and $d_i$ is the direction veering type of the $i$-th force point. A force point with a type
'>' changes protons direction to the positive direction of the $x$-axis, 'v' represents the positive
direction of the $y$-axis, '<' represents the negative direction of the $x$-axis, and '^' represents the
negative direction of the $y$-axis. You can assume that any two Force Points are not generated
on the same
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
      
#define FOR(i,a,b) for( ll i = (a); i < (ll)(b); i++ )
#define REP(i,n) FOR(i,0,n)
#define YYS(x,arr) for(auto& x:arr)
#define ALL(x) (x).begin(),(x).end()
#define SORT(x) sort( (x).begin(),(x).end() )
#define REVERSE(x) reverse( (x).begin(),(x).end() )
#define UNIQUE(x) (x).erase( unique( ALL( (x) ) ) , (x).end() )
#define PW(x) (1LL<<(x))
#define SZ(x) ((ll)(x).size())
#define SHOW(x) cout << #x << " = " << x << endl
#define SHOWA(x,n) for( int yui = 0; yui < n; yui++ ){ cout << x[yui] << " "; } cout << endl

#define pb emplace_back
#define fi first
#define se second

using namespace std;

typedef long double ld;
typedef long long int ll;
typedef pair<int,int> pi;
typedef pair<ll,ll> pl;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<bool> vb;
typedef vector<ld> vd;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<vpl> gr;
typedef vector<vl> ml;
typedef vector<vd> md;
typedef vector<vi> mi;
     
const ll INF = (ll)1e9 + 10;
const ll INFLL = (ll)1e18 + 10;
const ld EPS = 1e-12;
const ll MOD = 1e9+7;
     
template<class T> T &chmin( T &a , const T &b ){ return a = min(a,b); }
template<class T> T &chmax( T &a , const T &b ){ return a = max(a,b); }
template<class T> inline T sq( T a ){ return a * a; }

ll in(){ long long int x; scanf( "%lld" , &x ); return x; }
char yuyushiki[1000010]; string stin(){ scanf( "%s" , yuyushiki ); return yuyushiki; }

// head

template<class T> vi compress( vector<T> a ){
  vector<T> ord = a;
  vi res(0);
  SORT( ord );
  UNIQUE( ord );
  YYS( w , a ) res.pb( lower_bound( ALL(ord) , w ) - ord.begin() );
  return res;
}

int n;

vi xs, ys;
int d[3010];

set<pi> px[3010];
set<pi> py[3010];

int ans = 0;

void check( int s ){
  REP( i , 3010 ){
    px[i].clear();
    py[i].clear();
  }
  REP( i , n ){
    px[ xs[i] ].insert( pi( ys[i] , i ) );
    py[ ys[i] ].insert( pi( xs[i] , i ) );
  }
  
  int res = 0;
  int cur = s;

  while( 1 ){
    int cd = d[cur];
    res++;
    int x = xs[cur];
    int y = ys[cur];
    px[x].erase( pi( y , cur ) );
    py[y].erase( pi( x , cur ) );

    if( cd == 0 ){
      auto ite = py[y].lower_bound( pi( x , 0 ) );
      if( ite == py[y].end() ){
        break;
      }
      cur = (*ite).se;
    } else if( cd == 1 ){
      auto ite = px[x].lower_bound( pi( y , 0 ) );
      if( ite == px[x].begin() ){
        break;
      }
      ite--;
      cur = (*ite).se;
    } else if( cd == 2 ){
      auto ite = py[y].lower_bound( pi( x , 0 ) );
      if( ite == py[y].begin() ){
        break;
      }
      ite--;
      cur = (*ite).se;
    } else if( cd == 3 ){
      auto ite = px[x].lower_bound( pi( y , 0 ) );
      if( ite == px[x].end() ){
        break;
      }
      cur = (*ite).se;
    } else {
      assert( false );
    }
  }
  
  chmax( ans , res );
}

int main(){

  n = in();

  REP( i , n ){
    int x = in();
    int y = in();
    xs.pb( x );
    ys.pb( y );
    string s = stin();
    if( s[0] == '>' ){
      d[i] = 0;
    } else if( s[0] == '^' ){
      d[i] = 1;
    } else if( s[0] == '<' ){
      d[i] = 2;
    } else if( s[0] == 'v' ){
      d[i] = 3;
    } else {
      assert( false );
    }
  }

  xs = compress( xs );
  ys = compress( ys );

  REP( i , n ){
    check( i );
  }

  cout << ans << endl;
  
  return 0;
}
accuracy: 1
time_ms: 1460
memory_kb: 4096
final_rank: 10

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define rep(i, m, n) for (ll i = (ll)m; i < (ll)n; i++)
#define drep(i, m, n) for (ll i = m - 1; i >= n; i--)
#define Endl endl
#define all(a) a.begin(), a.end()
#define pr(i, j) make_pair(i, j)
#define isin(x, l, r) (l <= x && x < r)
#define chmin(a, b) a = min(a, b)
#define chmax(a, b) a = max(a, b)
#define srt(ar) sort(ar.begin(), ar.end())
#define rev(ar) reverse(ar.begin(), ar.end())
#define jge(f, s, t) cout << (f ? s : t) << endl
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#define printar(ar)             \
    do                          \
    {                           \
        for (auto dbg : ar)     \
        {                       \
            cout << dbg << " "; \
        }                       \
        cout << endl;           \
    } while (0)
const ll inf = 1e18;
const ld pi = 3.14159265358979;
const ld eps = 1e-9;
template <class T, ll n, ll idx = 0>
auto make_vec(const ll (&d)[n], const T &init) noexcept
{
    if constexpr (idx < n)
        return std::vector(d[idx], make_vec<T, n, idx + 1>(d, init));
    else
        return init;
}

template <class T, ll n>
auto make_vec(const ll (&d)[n]) noexcept
{
    return make_vec(d, T{});
}
//////////////// 以下を貼る ////////////////
template <class T>
size_t HashCombine(const size_t seed, const T &v)
{
    return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
/* pair用 */
template <class T, class S>
struct std::hash<std::pair<T, S>>
{
    size_t operator()(const std::pair<T, S> &keyval) const noexcept
    {
        return HashCombine(std::hash<T>()(keyval.first), keyval.second);
    }
};
////////////////////////////////////////////
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n;
    cin >> n;
    map<ll, set<pair<ll, ll>>> mpx, mpy;
    vector<ll> X(n), Y(n);
    rep(i, 0, n)
    {
        ll x, y;
        string s;
        cin >> x >> y >> s;
        ll t = -1;
        if (s == "<")
        {
            t = 0;
        }
        if (s == ">")
        {
            t = 1;
        }
        if (s == "^")
        {
            t = 2;
        }
        if (s == "v")
        {
            t = 3;
        }
        mpx[x].insert(pr(y, t));
        mpy[y].insert(pr(x, t));
        X[i] = x;
        Y[i] = y;
    }
    ll ans = 0;
    rep(i, 0, n)
    {
        map<ll, set<pair<ll, ll>>> cpx = mpx;
        map<ll, set<pair<ll, ll>>> cpy = mpy;
        ll x = X[i];
        ll y = Y[i];
        ll t = 0;
        ll sub = 0;
        // cout << ">>>>" << i << endl;
        while (true)
        {
            if (t == 0)
            {
                auto itr = cpy[y].upper_bound(pr(x, 10));
                if (itr == cpy[y].begin())
                {
                    break;
                }
                pair<ll, ll> nxt = *prev(itr);
                x = nxt.first;
                t = nxt.second;
            }
            else if (t == 1)
            {
                auto itr = cpy[y].lower_bound(pr(x, -2));
                if (itr == cpy[y].end())
                {
                    break;
                }
                pair<ll, ll> nxt = *(itr);
                x = nxt.first;
                t = nxt.second;
            }
            else if (t == 2)
            {
                auto itr = cpx[x].upper_bound(pr(y, 10));
                if (itr == cpx[x].begin())
                {
                    break;
                }
                pair<ll, ll> nxt = *prev(itr);
                y = nxt.first;
                t = nxt.second;
            }
            else if (t == 3)
            {
                auto itr = cpx[x].lower_bound(pr(y, -2));
                if (itr == cpx[x].end())
                {
                    break;
                }
                pair<ll, ll> nxt = *(itr);
                y = nxt.first;
                t = nxt.second;
            }
            // cout << x << " " << y << " " << t << endl;
            cpx[x].erase(pr(y, t));
            cpy[y].erase(pr(x, t));
            sub++;
        }
        // cout << sub << endl;
        chmax(ans, sub);
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 1700
memory_kb: 4992
final_rank: 16

code_snippet: // AOJ #2718
// Vector Field 2025.2.2

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct ForcePoint {
    ll x, y;
    char d;
    int rowPrev, rowNext;
    int colPrev, colNext;
};

struct Change {
    int which;
    int i;
    int oldVal;
    int newVal;
};

inline void applyChange(vector<int> &linkArr, int whichArr,
                        int i, int newVal,
                        vector<Change> &history)
{
    int oldVal = linkArr[i];
    if(oldVal == newVal) return; // 変化なしなら記録不要
    history.push_back({whichArr, i, oldVal, newVal});
    linkArr[i] = newVal;
}

inline void rollback(vector<int> &rowPrev,
                     vector<int> &rowNext,
                     vector<int> &colPrev,
                     vector<int> &colNext,
                     vector<Change> &history)
{
    while(!history.empty()){
        auto &c = history.back();
        switch(c.which){
            case 0: rowPrev[c.i] = c.oldVal; break;
            case 1: rowNext[c.i] = c.oldVal; break;
            case 2: colPrev[c.i] = c.oldVal; break;
            case 3: colNext[c.i] = c.oldVal; break;
        }
        history.pop_back();
    }
}

inline void removePoint(int i,
                       vector<int> &rowPrev,
                       vector<int> &rowNext,
                       vector<int> &colPrev,
                       vector<int> &colNext,
                       vector<Change> &history)
{
    {
        int lp = rowPrev[i];
        int ln = rowNext[i];
        if(lp != -1){
            applyChange(rowNext, 1, lp, ln, history);
        }
        if(ln != -1){
            applyChange(rowPrev, 0, ln, lp, history);
        }
    }
    {
        int up = colPrev[i];
        int un = colNext[i];
        if(up != -1){
            applyChange(colNext, 3, up, un, history);
        }
        if(un != -1){
            applyChange(colPrev, 2, un, up, history);
        }
    }
}

int getNextPoint(int i, const vector<ForcePoint> &P,
                 const vector<int> &rowPrev,
                 const vector<int> &rowNext,
                 const vector<int> &colPrev,
                 const vector<int> &colNext)
{
    char d = P[i].d;
    if(d == '>') return rowNext[i];
    if(d == '<') return rowPrev[i];
    if(d == 'v') return colNext[i];
    return colPrev[i]; // d == '^'
}

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

    int n;
    cin >> n;
    vector<ForcePoint> P(n);

    for(int i=0; i<n; i++){
        cin >> P[i].x >> P[i].y >> P[i].d;
        P[i].rowPrev = P[i].rowNext = -1;
        P[i].colPrev = P[i].colNext = -1;
    }

    {
        unordered_map<ll, vector<pair<ll,int>>> rowMap;
        rowMap.reserve(n);
        rowMap.max_load_factor(0.7f);

        for(int i=0; i<n; i++){
            rowMap[P[i].y].push_back({P[i].x, i});
        }
        for(auto &rv : rowMap){
            auto &vecRow = rv.second;
            sort(vecRow.begin(), vecRow.end());
            for(int k=0; k<(int)vecRow.size(); k++){
                auto [xk, ik] = vecRow[k];
                if(k>0){
                    auto [xk_1, ik_1] = vecRow[k-1];
                    P[ik].rowPrev = ik_1;
                    P[ik_1].rowNext = ik;
                }
            }
        }
    }
    {
        unordered_map<ll, vector<pair<ll,int>>> colMap;
        colMap.reserve(n);
        colMap.max_load_factor(0.7f);

        for(int i=0; i<n; i++){
            colMap[P[i].x].push_back({P[i].y, i});
        }
        for(auto &cv : colMap){
            auto &vecCol = cv.second;
            sort(vecCol.begin(), vecCol.end());
            for(int k=0; k<(int)vecCol.size(); k++){
                auto [yk, ik] = vecCol[k];
                if(k>0){
                    auto [yk_1, ik_1] = vecCol[k-1];
                    P[ik].colPrev = ik_1;
                    P[ik_1].colNext = ik;
                }
            }
        }
    }

    vector<int> rowPrev(n), rowNext(n), colPrev(n), colNext(n);
    for(int i=0;i<n;i++){
        rowPrev[i] = P[i].rowPrev;
        rowNext[i] = P[i].rowNext;
        colPrev[i] = P[i].colPrev;
        colNext[i] = P[i].colNext;
    }

    int answer = 0;
    for(int start=0; start<n; start++){
        vector<Change> history;
        int countStep = 0;
        int cur = start;
        while(cur != -1){
            countStep++;
            removePoint(cur, rowPrev, rowNext, colPrev, colNext, history);
            int nxt = getNextPoint(cur, P, rowPrev, rowNext, colPrev, colNext);
            cur = nxt;
        }
        answer = max(answer, countStep);
        rollback(rowPrev, rowNext, colPrev, colNext, history);
    }
    cout << answer << endl;
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3744
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define srep(i, s, t) for(int i = (s); i < (t); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
using i64 = long long;
using f64 = long double;
i64 floor_div(const i64 n, const i64 d) { assert(d != 0); return n / d - static_cast<i64>((n ^ d) <  0 && n % d != 0); }
i64  ceil_div(const i64 n, const i64 d) { assert(d != 0); return n / d + static_cast<i64>((n ^ d) >= 0 && n % d != 0); }

int main() {
    cin.tie(0)->sync_with_stdio(0);
    
    int n; cin >> n;
    vector<int> x(n), y(n);
    vector<char> d(n);
    rep(i, n) cin >> x[i] >> y[i] >> d[i];

    vector<int> vx = x, vy = y;
    sort(vx.begin(), vx.end());
    sort(vy.begin(), vy.end());
    vx.erase(unique(vx.begin(), vx.end()), vx.end());
    vy.erase(unique(vy.begin(), vy.end()), vy.end());
    for(auto& e : x) e = lower_bound(vx.begin(), vx.end(), e) - vx.begin();
    for(auto& e : y) e = lower_bound(vy.begin(), vy.end(), e) - vy.begin();
    const int mx = vx.size(), my = vy.size();

    vector<set<pair<int, int>>> ys(mx), xs(my);
    
    auto F = [&](int s) -> int {
        rep(i, mx) ys.clear();
        rep(i, my) xs.clear();
        rep(i, n) {
            ys[x[i]].insert({y[i], i});
            xs[y[i]].insert({x[i], i});
        }

        int ans = 0;
        int i = s;
        while(true) {
            ans++;
            ys[x[i]].erase({y[i], i});
            xs[y[i]].erase({x[i], i});

            if(d[i] == 'v') {
                auto itr = ys[x[i]].lower_bound({y[i], -1});
                if(itr == ys[x[i]].end()) break;
                i = itr->second;
            } else if(d[i] == '^') {
                auto itr = ys[x[i]].lower_bound({y[i], -1});
                if(itr == ys[x[i]].begin()) break;
                i = prev(itr)->second;
            } else if(d[i] == '>') {
                auto itr = xs[y[i]].lower_bound({x[i], -1});
                if(itr == xs[y[i]].end()) break;
                i = itr->second;
            } else {
                auto itr = xs[y[i]].lower_bound({x[i], -1});
                if(itr == xs[y[i]].begin()) break;
                i = prev(itr)->second;
            }
        }
        return ans;
    };

    int ans = 0;
    rep(i, n) chmax(ans, F(i));
    cout << ans << "\n";
}
accuracy: 1
time_ms: 1510
memory_kb: 3932
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int N;
    cin >> N;
    vector<int> X(N), Y(N), D(N), XS, YS;
    rep(i,0,N) {
        cin >> X[i] >> Y[i];
        char C;
        cin >> C;
        if (C == '>') D[i] = 0;
        if (C == 'v') D[i] = 1;
        if (C == '<') D[i] = 2;
        if (C == '^') D[i] = 3;
        XS.push_back(X[i]), YS.push_back(Y[i]);
    }
    UNIQUE(XS), UNIQUE(YS);
    rep(i,0,N) X[i] = LB(XS,X[i]), Y[i] = LB(YS,Y[i]);
    int ANS = 0;
    rep(i,0,N) {
        map<pair<int,int>,int> mpX, mpY;
        rep(j,0,N) mpX[{X[j],Y[j]}] = j, mpY[{Y[j],X[j]}] = j;
        mpX[{-inf,-inf}] = mpX[{inf,inf}] = -1;
        mpY[{-inf,-inf}] = mpY[{inf,inf}] = -1;
        int CurX = X[i], CurY = Y[i], dir = D[i], id = i;
        int COUNT = 0;
        while(1) {
            CurX = X[id], CurY = Y[id], dir = D[id];
            COUNT++;
            mpX.erase({X[id],Y[id]});
            mpY.erase({Y[id],X[id]});
            if (dir == 0) {
                auto it = mpY.lower_bound({CurY, CurX});
                if (it->first.first != CurY) break;
                id = it->second;
            }
            else if (dir == 1) {
                auto it = mpX.lower_bound({CurX,CurY});
                if (it->first.first != CurX) break;
                id = it->second;
            }
            else if (dir == 2) {
                auto it = mpY.upper_bound({CurY,CurX});
                it--;
                if (it->first.first != CurY) break;
                id = it->second;
            }
            else {
                auto it = mpX.upper_bound({CurX,CurY});
                it--;
                if (it->first.first != CurX) break;
                id = it->second;
            }
        }
        chmax(ANS,COUNT);
    }
    cout << ANS << endl;
}
accuracy: 1
time_ms: 2940
memory_kb: 3840
final_rank: 18

code_snippet: #include <bits/stdc++.h>

#include <limits>
#include <type_traits>

namespace suisen {
// ! utility
template <typename ...Types>
using constraints_t = std::enable_if_t<std::conjunction_v<Types...>, std::nullptr_t>;
template <bool cond_v, typename Then, typename OrElse>
constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) {
    if constexpr (cond_v) {
        return std::forward<Then>(then);
    } else {
        return std::forward<OrElse>(or_else);
    }
}

// ! function
template <typename ReturnType, typename Callable, typename ...Args>
using is_same_as_invoke_result = std::is_same<std::invoke_result_t<Callable, Args...>, ReturnType>;
template <typename F, typename T>
using is_uni_op = is_same_as_invoke_result<T, F, T>;
template <typename F, typename T>
using is_bin_op = is_same_as_invoke_result<T, F, T, T>;

template <typename Comparator, typename T>
using is_comparator = std::is_same<std::invoke_result_t<Comparator, T, T>, bool>;

// ! integral
template <typename T, typename = constraints_t<std::is_integral<T>>>
constexpr int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits;
template <typename T, unsigned int n>
struct is_nbit { static constexpr bool value = bit_num<T> == n; };
template <typename T, unsigned int n>
static constexpr bool is_nbit_v = is_nbit<T, n>::value;

// ?
template <typename T>
struct safely_multipliable {};
template <>
struct safely_multipliable<int> { using type = long long; };
template <>
struct safely_multipliable<long long> { using type = __int128_t; };
template <>
struct safely_multipliable<unsigned int> { using type = unsigned long long; };
template <>
struct safely_multipliable<unsigned long int> { using type = __uint128_t; };
template <>
struct safely_multipliable<unsigned long long> { using type = __uint128_t; };
template <>
struct safely_multipliable<float> { using type = float; };
template <>
struct safely_multipliable<double> { using type = double; };
template <>
struct safely_multipliable<long double> { using type = long double; };
template <typename T>
using safely_multipliable_t = typename safely_multipliable<T>::type;

} // namespace suisen

// ! type aliases
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using pq_greater = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T, typename U>
using umap = std::unordered_map<T, U>;

// ! macros (capital: internal macro)
#define OVERLOAD2(_1,_2,name,...) name
#define OVERLOAD3(_1,_2,_3,name,...) name
#define OVERLOAD4(_1,_2,_3,_4,name,...) name

#define REP4(i,l,r,s)  for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l);i<(r);i+=(s))
#define REP3(i,l,r)    REP4(i,l,r,1)
#define REP2(i,n)      REP3(i,0,n)
#define REPINF3(i,l,s) for(std::remove_reference_t<std::remove_const_t<decltype(l)>>i=(l);;i+=(s))
#define REPINF2(i,l)   REPINF3(i,l,1)
#define REPINF1(i)     REPINF2(i,0)
#define RREP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s))
#define RREP3(i,l,r)   RREP4(i,l,r,1)
#define RREP2(i,n)     RREP3(i,0,n)

#define rep(...)    OVERLOAD4(__VA_ARGS__, REP4   , REP3   , REP2   )(__VA_ARGS__)
#define rrep(...)   OVERLOAD4(__VA_ARGS__, RREP4  , RREP3  , RREP2  )(__VA_ARGS__)
#define repinf(...) OVERLOAD3(__VA_ARGS__, REPINF3, REPINF2, REPINF1)(__VA_ARGS__)

#define CAT_I(a, b) a##b
#define CAT(a, b) CAT_I(a, b)
#define UNIQVAR(tag) CAT(tag, __LINE__)
#define loop(n) for (std::remove_reference_t<std::remove_const_t<decltype(n)>> UNIQVAR(loop_variable) = n; UNIQVAR(loop_variable) --> 0;)

#define all(iterable) std::begin(iterable), std::end(iterable)
#define input(type, ...) type __VA_ARGS__; read(__VA_ARGS__)

#ifdef LOCAL
#  define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__)

template <class T, class... Args>
void debug_internal(const char* s, T&& first, Args&&... args) {
    constexpr const char* prefix = "[\033[32mDEBUG\033[m] ";
    constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "(";
    constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")";
    std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward<T>(first);
    ((std::cerr << ", " << std::forward<Args>(args)), ...);
    std::cerr << close_brakets << "\n";
}

#else
#  define debug(...) void(0)
#endif

// ! I/O utilities

// pair
template <typename T, typename U>
std::ostream& operator<<(std::ostream& out, const std::pair<T, U> &a) {
    return out << a.first << ' ' << a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::ostream& operator<<(std::ostream& out, const std::tuple<Args...> &a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return out;
    } else {
        out << std::get<N>(a);
        if constexpr (N + 1 < std::tuple_size_v<std::tuple<Args...>>) {
            out << ' ';
        }
        return operator<<<N + 1>(out, a);
    }
}
// vector
template <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T> &a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
// array
template <typename T, size_t N>
std::ostream& operator<<(std::ostream& out, const std::array<T, N> &a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
inline void print() { std::cout << '\n'; }
template <typename Head, typename... Tail>
inline void print(const Head &head, const Tail &...tails) {
    std::cout << head;
    if (sizeof...(tails)) std::cout << ' ';
    print(tails...);
}
template <typename Iterable>
auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) {
    for (auto it = v.begin(); it != v.end();) {
        std::cout << *it;
        if (++it != v.end()) std::cout << sep;
    }
    std::cout << end;
}

// pair
template <typename T, typename U>
std::istream& operator>>(std::istream& in, std::pair<T, U> &a) {
    return in >> a.first >> a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::istream& operator>>(std::istream& in, std::tuple<Args...> &a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return in;
    } else {
        return operator>><N + 1>(in >> std::get<N>(a), a);
    }
}
// vector
template <typename T>
std::istream& operator>>(std::istream& in, std::vector<T> &a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
// array
template <typename T, size_t N>
std::istream& operator>>(std::istream& in, std::array<T, N> &a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
template <typename ...Args>
void read(Args &...args) {
    ( std::cin >> ... >> args );
}

// ! integral utilities

// Returns pow(-1, n)
template <typename T>
constexpr inline int pow_m1(T n) {
    return -(n & 1) | 1;
}
// Returns pow(-1, n)
template <>
constexpr inline int pow_m1<bool>(bool n) {
    return -int(n) | 1;
}

// Returns floor(x / y)
template <typename T>
constexpr inline T fld(const T x, const T y) {
    return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y;
}
template <typename T>
constexpr inline T cld(const T x, const T y) {
    return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y;
}

template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int popcount(const T x) { return __builtin_popcount(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int popcount(const T x) { return __builtin_popcount(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int popcount(const T x) { return __builtin_popcountll(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x)   : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x)   : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x)   : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x)   : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num<T>; }
template <typename T>
constexpr inline int floor_log2(const T x) { return suisen::bit_num<T> - 1 - count_lz(x); }
template <typename T>
constexpr inline int ceil_log2(const T x)  { return floor_log2(x) + ((x & -x) != x); }
template <typename T>
constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; }
template <typename T>
constexpr inline int parity(const T x) { return popcount(x) & 1; }

struct all_subset {
    struct all_subset_iter {
        const int s; int t;
        constexpr all_subset_iter(int s) : s(s), t(s + 1) {}
        constexpr auto operator*() const { return t; }
        constexpr auto operator++() {}
        constexpr auto operator!=(std::nullptr_t) { return t ? (--t &= s, true) : false; }
    };
    int s;
    constexpr all_subset(int s) : s(s) {}
    constexpr auto begin() { return all_subset_iter(s); }
    constexpr auto end()   { return nullptr; }
};

// ! container

template <typename T, typename Comparator, suisen::constraints_t<suisen::is_comparator<Comparator, T>> = nullptr>
auto priqueue_comp(const Comparator comparator) {
    return std::priority_queue<T, std::vector<T>, Comparator>(comparator);
}

template <typename Iterable>
auto isize(const Iterable &iterable) -> decltype(int(iterable.size())) {
    return iterable.size();
}

template <typename T, typename Gen, suisen::constraints_t<suisen::is_same_as_invoke_result<T, Gen, int>> = nullptr>
auto generate_vector(int n, Gen generator) {
    std::vector<T> v(n);
    for (int i = 0; i < n; ++i) v[i] = generator(i);
    return v;
}
template <typename T>
auto generate_range_vector(T l, T r) {
    return generate_vector(r - l, [l](int i) { return l + i; });
}
template <typename T>
auto generate_range_vector(T n) {
    return generate_range_vector(0, n);
}

template <typename T>
void sort_unique_erase(std::vector<T> &a) {
    std::sort(a.begin(), a.end());
    a.erase(std::unique(a.begin(), a.end()), a.end());
}

template <typename InputIterator, typename BiConsumer>
auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) {
    if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr);
}
template <typename Container, typename BiConsumer>
auto foreach_adjacent_values(Container c, BiConsumer f) -> decltype(c.begin(), c.end(), void()){
    foreach_adjacent_values(c.begin(), c.end(), f);
}

// ! other utilities

// x <- min(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmin(T &x, const T &y) {
    if (y >= x) return false;
    x = y;
    return true;
}
// x <- max(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmax(T &x, const T &y) {
    if (y <= x) return false;
    x = y;
    return true;
}

namespace suisen {}
using namespace suisen;
using namespace std;

struct io_setup {
    io_setup(int precision = 20) {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(precision);
    }
} io_setup_ {};

// ! code from here

#include <algorithm>
#include <cassert>
#include <vector>

namespace suisen {
template <typename T>
class CoordinateCompressorBuilder {
    public:
        struct Compressor {
            public:
                static constexpr int absent = -1;

                // default constructor
                Compressor() : _xs(std::vector<T>{}) {}
                // Construct from strictly sorted vector
                Compressor(const std::vector<T> &xs) : _xs(xs) {
                    assert(is_strictly_sorted(xs));
                }

                // Return the number of distinct keys.
                int size() const {
                    return _xs.size();
                }
                // Check if the element is registered.
                bool has_key(const T &e) const {
                    return std::binary_search(_xs.begin(), _xs.end(), e);
                }
                // Compress the element. if not registered, returns `default_value`. (default: Compressor::absent)
                int comp(const T &e, int default_value = absent) const {
                    const int res = min_geq_index(e);
                    return res != size() and _xs[res] == e ? res : default_value;
                }
                // Restore the element from the index.
                T decomp(const int compressed_index) const {
                    return _xs[compressed_index];
                }
                // Compress the element. Equivalent to call `comp(e)`
                int operator[](const T &e) const {
                    return comp(e);
                }
                // Return the minimum registered value greater than `e`. if not exists, return `default_value`.
                T min_gt(const T &e, const T &default_value) const {
                    auto it = std::upper_bound(_xs.begin(), _xs.end(), e);
                    return it == _xs.end() ? default_value : *it;
                }
                // Return the minimum registered value greater than or equal to `e`. if not exists, return `default_value`.
                T min_geq(const T &e, const T &default_value) const {
                    auto it = std::lower_bound(_xs.begin(), _xs.end(), e);
                    return it == _xs.end() ? default_value : *it;
                }
                // Return the maximum registered value less than `e`. if not exists, return `default_value`
                T max_lt(const T &e, const T &default_value) const {
                    auto it = std::upper_bound(_xs.rbegin(), _xs.rend(), e, std::greater<T>());
                    return it == _xs.rend() ? default_value : *it;
                }
                // Return the maximum registered value less than or equal to `e`. if not exists, return `default_value`
                T max_leq(const T &e, const T &default_value) const {
                    auto it = std::lower_bound(_xs.rbegin(), _xs.rend(), e, std::greater<T>());
                    return it == _xs.rend() ? default_value : *it;
                }
                // Return the compressed index of the minimum registered value greater than `e`. if not exists, return `compressor.size()`.
                int min_gt_index(const T &e) const {
                    return std::upper_bound(_xs.begin(), _xs.end(), e) - _xs.begin();
                }
                // Return the compressed index of the minimum registered value greater than or equal to `e`. if not exists, return `compressor.size()`.
                int min_geq_index(const T &e) const {
                    return std::lower_bound(_xs.begin(), _xs.end(), e) - _xs.begin();
                }
                // Return the compressed index of the maximum registered value less than `e`. if not exists, return -1.
                int max_lt_index(const T &e) const {
                    return int(_xs.rend() - std::upper_bound(_xs.rbegin(), _xs.rend(), e, std::greater<T>())) - 1;
                }
                // Return the compressed index of the maximum registered value less than or equal to `e`. if not exists, return -1.
                int max_leq_index(const T &e) const {
                    return int(_xs.rend() - std::lower_bound(_xs.rbegin(), _xs.rend(), e, std::greater<T>())) - 1;
                }
            private:
                std::vector<T> _xs;
                static bool is_strictly_sorted(const std::vector<T> &v) {
                    return std::adjacent_find(v.begin(), v.end(), std::greater_equal<T>()) == v.end();
                }
        };
        CoordinateCompressorBuilder() : _xs(std::vector<T>{}) {}
        explicit CoordinateCompressorBuilder(const std::vector<T> &xs) : _xs(xs) {}
        explicit CoordinateCompressorBuilder(std::vector<T> &&xs) : _xs(std::move(xs)) {}
        template <typename Gen, constraints_t<is_same_as_invoke_result<T, Gen, int>> = nullptr>
        CoordinateCompressorBuilder(const int n, Gen generator) {
            reserve(n);
            for (int i = 0; i < n; ++i) push(generator(i));
        }
        // Attempt to preallocate enough memory for specified number of elements.
        void reserve(int n) {
            _xs.reserve(n);
        }
        // Add data.
        void push(const T &first) {
            _xs.push_back(first);
        }
        // Add data.
        void push(T &&first) {
            _xs.push_back(std::move(first));
        }
        // Add data in the range of [first, last). 
        template <typename Iterator>
        auto push(const Iterator &first, const Iterator &last) -> decltype(std::vector<T>{}.push_back(*first), void()) {
            for (auto it = first; it != last; ++it) _xs.push_back(*it);
        }
        // Add all data in the container. Equivalent to `push(iterable.begin(), iterable.end())`.
        template <typename Iterable>
        auto push(const Iterable &iterable) -> decltype(std::vector<T>{}.push_back(*iterable.begin()), void()) {
            push(iterable.begin(), iterable.end());
        }
        // Add data.
        template <typename ...Args>
        void emplace(Args &&...args) {
            _xs.emplace_back(std::forward<Args>(args)...);
        }
        // Build compressor.
        auto build() {
            std::sort(_xs.begin(), _xs.end()), _xs.erase(std::unique(_xs.begin(), _xs.end()), _xs.end());
            return Compressor {_xs};
        }
        // Build compressor from vector.
        static auto build(const std::vector<T> &xs) {
            return CoordinateCompressorBuilder(xs).build();
        }
        // Build compressor from vector.
        static auto build(std::vector<T> &&xs) {
            return CoordinateCompressorBuilder(std::move(xs)).build();
        }
        // Build compressor from generator.
        template <typename Gen, constraints_t<is_same_as_invoke_result<T, Gen, int>> = nullptr>
        static auto build(const int n, Gen generator) {
            return CoordinateCompressorBuilder<T>(n, generator).build();
        }
    private:
        std::vector<T> _xs;
};

} // namespace suisen

int dx4[5] = { 0, 1, 0, -1, 0 };
int dy4[5] = { 0, 0, 1, 0, -1 };

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
constexpr int bsf_constexpr(unsigned int n) {
    int x = 0;
    while (!(n & (1 << x))) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder

namespace atcoder {

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
  public:
    segtree() : segtree(0) {}
    explicit segtree(int n) : segtree(std::vector<S>(n, e())) {}
    explicit segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) const {
        assert(0 <= p && p < _n);
        return d[p + size];
    }

    S prod(int l, int r) const {
        assert(0 <= l && l <= r && r <= _n);
        S sml = e(), smr = e();
        l += size;
        r += size;

        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }

    S all_prod() const { return d[1]; }

    template <bool (*f)(S)> int max_right(int l) const {
        return max_right(l, [](S x) { return f(x); });
    }
    template <class F> int max_right(int l, F f) const {
        assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*f)(S)> int min_left(int r) const {
        return min_left(r, [](S x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) const {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

}  // namespace atcoder

namespace fast_set {
    int op(int x, int y) {
        return x + y;
    }
    int e() {
        return 0;
    }

    struct FastSet {
        int n;
        atcoder::segtree<int, op, e> seg;

        FastSet() : FastSet(0) {}
        FastSet(int n) : n(n), seg(n) {}

        int get(int x) {
            return seg.get(x);
        }
        void add(int x, int v) {
            seg.set(x, seg.get(x) + v);
        }
        void sub(int x, int v) {
            seg.set(x, seg.get(x) - v);
        }

        int nxt(int x) {
            return seg.max_right(x, [&](int e) { return e == 0; });
        }
        int pre(int x) {
            return seg.min_left(x, [&](int e) { return e == 0; }) - 1;
        }
    };
};

using fast_set::FastSet;

constexpr int R = 1, U = 2, L = 3, D = 4;

int main() {
    array<int, 256> dir{};
    dir['>'] = R;
    dir['v'] = U;
    dir['<'] = L;
    dir['^'] = D;

    CoordinateCompressorBuilder<int> bx, by;

    input(int, n);
    vector<tuple<int, int, int>> ps(n);
    rep(i, n) {
        input(int, x, y);
        input(char, c);
        ps[i] = { x, y, dir[c] };
        bx.push(x);
        by.push(y);
        assert(1 <= dir[c] and dir[c] <= 4);
    }

    const auto cmpx = bx.build(), cmpy = by.build();
    for (auto &[x, y, d] : ps) {
        x = cmpx[x];
        y = cmpy[y];
    }
    const int h = cmpx.size();
    const int w = cmpy.size();

    vector<CoordinateCompressorBuilder<int>> bxy(h), byx(w);
    for (auto &[x, y, d] : ps) {
        bxy[x].push(y);
        byx[y].push(x);
    }
    vector<CoordinateCompressorBuilder<int>::Compressor> cmp_xy(h), cmp_yx(w);
    rep(i, h) {
        cmp_xy[i] = bxy[i].build();
    }
    rep(j, w) {
        cmp_yx[j] = byx[j].build();
    }

    int ans = 0;
    rep(i, n) {
        vector<FastSet> x_to_y(h), y_to_x(w);
        rep(k, h) {
            x_to_y[k] = FastSet(cmp_xy[k].size());
        }
        rep(k, w) {
            y_to_x[k] = FastSet(cmp_yx[k].size());
        }

        rep(j, n) if (j != i) {
            auto [x, y, d] = ps[j];
            x_to_y[x].add(cmp_xy[x][y], d);
            y_to_x[y].add(cmp_yx[y][x], d);
        }

        debug(i);
        int cnt = 0;
        auto [cx, cy, cd] = ps[i];
        while (0 <= cx and cx < h and 0 <= cy and cy < w) {
            debug(cx, cy, cd);
            ++cnt;
            if (cd == R) {
                int xi = cmp_yx[cy][cx];
                int ni = y_to_x[cy].nxt(xi);
                if (ni == cmp_yx[cy].size()) break;

                cx = cmp_yx[cy].decomp(ni);
                cd = y_to_x[cy].get(ni);

                y_to_x[cy].sub(ni, cd);
                x_to_y[cx].sub(cmp_xy[cx][cy], cd);
            } else if (cd == L) {
                int xi = cmp_yx[cy][cx];
                int ni = y_to_x[cy].pre(xi);
                if (ni == -1) break;

                cx = cmp_yx[cy].decomp(ni);
                cd = y_to_x[cy].get(ni);

                y_to_x[cy].sub(ni, cd);
                x_to_y[cx].sub(cmp_xy[cx][cy], cd);
            } else if (cd == U) {
                int yi = cmp_xy[cx][cy];
                int ni = x_to_y[cx].nxt(yi);
                if (ni == cmp_xy[cx].size()) break;

                cy = cmp_xy[cx].decomp(ni);
                cd = x_to_y[cx].get(ni);

                x_to_y[cx].sub(ni, cd);
                y_to_x[cy].sub(cmp_yx[cy][cx], cd);
            } else if (cd == D) {
                int yi = cmp_xy[cx][cy];
                int ni = x_to_y[cx].pre(yi);
                if (ni == -1) break;

                cy = cmp_xy[cx].decomp(ni);
                cd = x_to_y[cx].get(ni);

                x_to_y[cx].sub(ni, cd);
                y_to_x[cy].sub(cmp_yx[cy][cx], cd);
            } else {
                assert(false);
            }
        }

        chmax(ans, cnt);
    }

    print(ans);

    return 0;
}
accuracy: 1
time_ms: 1410
memory_kb: 4168
final_rank: 8

code_snippet: #include<bits/stdc++.h>
#define rep(i,a,...) for(int i = (a)*(strlen(#__VA_ARGS__)!=0);i<(int)(strlen(#__VA_ARGS__)?__VA_ARGS__:(a));++i)
#define per(i,a,...) for(int i = (strlen(#__VA_ARGS__)?__VA_ARGS__:(a))-1;i>=(int)(strlen(#__VA_ARGS__)?(a):0);--i)
#define foreach(i, n) for(auto &i:(n))
#define all(x) (x).begin(), (x).end()
#define bit(x) (1ll << (x))
#define lambda(RES_TYPE, ...) (function<RES_TYPE(__VA_ARGS__)>)[&](__VA_ARGS__) -> RES_TYPE
#define method(FUNC_NAME, RES_TYPE, ...) function<RES_TYPE(__VA_ARGS__)> FUNC_NAME = lambda(RES_TYPE, __VA_ARGS__)
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
//const ll MOD = (ll)1e9+7;
const ll MOD = 998244353;
const int INF = (ll)1e9+7;
const ll INFLL = (ll)1e18;
template<class t>
using vvector = vector<vector<t>>;
template<class t>
using vvvector = vector<vector<vector<t>>>;
template<class t>
using priority_queuer = priority_queue<t, vector<t>, greater<t>>;
template<class t, class u> bool chmax(t &a, u b){if(a<b){a=b;return true;}return false;}
template<class t, class u> bool chmin(t &a, u b){if(a>b){a=b;return true;}return false;}
#ifdef DEBUG
#define debug(x) cout<<"LINE "<<__LINE__<<": "<<#x<<" = "<<x<<endl;
#else
#define debug(x) (void)0
#endif

namespace templates{
    ll modpow(ll x, ll b,ll mod=MOD){
        ll res = 1;
        while(b){
            if(b&1)res = res * x % mod;
            x = x * x % mod;
            b>>=1;
        }
        return res;
    }

    ll modinv(ll x){
        return modpow(x, MOD-2);
    }

    bool was_output = false;

    void print();
    template <class t> void print(const vector<t> &);
    template <class t, class u> void print(const pair<t, u> &);
    template <class t> void print(const t&);
    template <class Head, class... Tail> void print(const Head&, const Tail&...);

    template <class t> void println(const vector<vector<t>>&);
    template <class t> void println(const vector<t>&);
    template <class t> void println(const t&);
    template <class Head, class... Tail> void println(const Head&, const Tail&...);
    void println();
    void newline();

    void print(){
        return;
    }

    template <class t>
    void print(const vector<t>&x){
        for(const t&i:x)print(i);
    }
    template <class t, class u>
    void print(const pair<t,u>&p){
        print(p.first);
        print(p.second);
    }
    template <class t>
    void print(const t&x){
        if(was_output)cout<<" ";
        cout<<x;
        was_output = true;
    }
    template <class Head, class... Tail>
    void print(const Head&head,const Tail&...tail){
        print(head);
        print(tail...);
    }

    template<class t>
    void println(const vector<vector<t>>&x){
        for(vector<t> i:x)println(i);
    }
    template<class t>
    void println(const vector<t>&x){
        for(const t&i:x)print(i);
        println();
    }
    template <class t>
    void println(const t&x){
        print(x);
        println();
    }
    void println(){
        if(was_output){
            cout << endl;
            was_output = false;
        }
    }
    template <class Head, class... Tail>
    void println(const Head&head,const Tail&...tail){
        print(head);
        println(tail...);
    }

    void newline(){
        was_output = true;
        println();
    }

    template<class t>
    istream& operator>>(istream&is, vector<t>&x){
        for(auto &i:x)is >> i;
        return is;
    }

    template<class t, class u>
    istream& operator>>(istream&is, pair<t, u>&x){
        is >> x.first >> x.second;
        return is;
    }

    template<class t>
    ostream& operator<<(ostream&os, vector<t> &v){
        os << "{";
        for(t &i:v){
            os << i << ", ";
        }
        os << "}";
        return os;
    }

    template<class t = long long>
    t in(){
        t res; cin >> res; return res;
    }

    template<class t>
    vector<t> sorted(vector<t> line,function<bool(t,t)> comp=[](t a,t b){return a<b;}){
        sort(line.begin(),line.end(),comp);
        return line;
    }

    template<class t>
    vector<t> reversed(vector<t> line){
        reverse(line.begin(),line.end());
        return line;
    }
    string reversed(string str){
        reverse(str.begin(),str.end());
        return str;
    }

    long long gcd(long long a,long long b){
        while(b){
            a %= b;
            swap(a,b);
        }
        return a;
    }

    long long lcm(long long a,long long b){
        return a / gcd(a,b) * b;
    }

    class output_initializer{
    public:
        output_initializer(){
            ios::sync_with_stdio(false);
            cin.tie(nullptr);
            cout << setprecision(20);
        }
    };output_initializer OUTPUT_INITIALIZER_INSTANCE = output_initializer();
}

using namespace templates;

int func(){
    int n = in();
    vvector<int> neis(n,vector<int>(4,-1));
    vector<int> dirs(n);
    map<char,int> char2int;
    char2int['^'] = 0;
    char2int['v'] = 1;
    char2int['>'] = 2;
    char2int['<'] = 3;
    {
        map<int,vector<pii>> ys;
        map<int,vector<pii>> xs;
        rep(i,n){
            int x = in();
            int y = in();
            ys[y].emplace_back(x,i);
            xs[x].emplace_back(y,i);
            dirs[i] = char2int[in<char>()];
        }
        foreach(i,xs){
            vector<int> ps;
            sort(all(i.second));
            foreach(j,i.second)ps.emplace_back(j.second);
            rep(j,ps.size()-1){
                neis[ps[j]][1] = ps[j+1];
                neis[ps[j+1]][0] = ps[j];
            }
        }
        foreach(i,ys){
            vector<int> ps;
            sort(all(i.second));
            foreach(j,i.second)ps.emplace_back(j.second);
            rep(j,ps.size()-1){
                neis[ps[j]][2] = ps[j+1];
                neis[ps[j+1]][3] = ps[j];
            }
        }
    }
    method(rev,int,int p){
        if(p==0)return 1;
        if(p==1)return 0;
        if(p==2)return 3;
        if(p==3)return 2;
        exit(1);
    };
    method(rec,int,int p){
        vector<int> bp = neis[p];
        rep(i,4){
            if(neis[p][i]>=0){
                swap(neis[neis[p][i]][rev(i)],bp[rev(i)]);
            }
        }
        int res = 0;
        int next = neis[p][dirs[p]];
        if(next>=0){
            res = rec(next);
        }
        rep(i,4){
            if(neis[p][i]>=0){
                swap(neis[neis[p][i]][rev(i)],bp[rev(i)]);
            }
        }
        return res + 1;
    };
    int res = 0;
    rep(i,n){
        chmax(res,rec(i));
    }
    return res;
}

int main(){
    println(func());
    return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 4340
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define _GLIBCXX_DEBUG
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=1167167167167167167;
const int INF=2100000000;
const ll mod=998244353;
#define rep(i,a) for (int i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}

void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	int N;
	cin>>N;
	string T="v^><";
	vector<int> X(N),Y(N),D(N);
	rep(i,N){
		cin>>X[i]>>Y[i];
		char c;
		cin>>c; 
		rep(k,4) if(c==T[k]) D[i]=k;
	}
	vector<vector<int>> base(N,vector<int>(4,-1));
	vector<int> order(N);rep(i,N) order[i]=i;
	sort(all(order),[&](int l,int r){
		if(X[l]==X[r]) return Y[l]<Y[r];
		return X[l]<X[r];
	});
	rep(i,N-1){
		if(X[order[i]]==X[order[i+1]]){
			base[order[i]][0]=order[i+1];
			base[order[i+1]][1]=order[i];
		}
	}
	sort(all(order),[&](int l,int r){
		if(Y[l]==Y[r]) return X[l]<X[r];
		return Y[l]<Y[r];
	});
	rep(i,N-1){
		if(Y[order[i]]==Y[order[i+1]]){
			base[order[i]][2]=order[i+1];
			base[order[i+1]][3]=order[i];
		}
	}
	vector<int> use(N);
	auto p=base;
	auto f=[&](auto self,int ind,int dir)->int{
		if(use[ind]==0){
			use[ind]=1;
			return ind;
		}
		if(p[ind][dir]==-1) return -1;
		return p[ind][dir]=self(self,p[ind][dir],dir);
	};
	int ans=0;
	rep(i,N){
		use[i]=1;
		int ind=i;
		int tmp=0;
		while(ind!=-1){
			ind=f(f,ind,D[ind]);
			tmp++;
		}
		chmax(ans,tmp);
		//cout<<tmp<<"\n";
		p=base;
		rep(k,N) use[k]=0;
	}
	cout<<ans<<"\n";
}
accuracy: 1
time_ms: 100
memory_kb: 3892
final_rank: 3

code_snippet: #include "bits/stdc++.h"
using namespace std;

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#define int long long
set<pair<int, int>> X_line[4000];
set<pair<int, int>> Y_line[4000];
void solve()
{
  const int dx[4] = {1, 0, -1, 0};
  const int dy[4] = {0, 1, 0, -1};
  int n;
  cin >> n;
  vector<tuple<int, int, int>> inputs;
  REP(i, n)
  {
    int a, b;
    string c;
    cin >> a >> b >> c;
    int d;
    if (c == ">")
    {
      d = 1;
    }
    else if (c == "<")
    {
      d = 3;
    }
    else if (c == "v")
    {
      d = 0;
    }
    else
    {
      d = 2;
    }
    inputs.push_back({b, a, d});
  }

  REP(t, 2)
  {
    map<int, int> cn;
    REP(i, n)
    {
      cn[get<0>(inputs[i])];
    }
    int cnter = 0;
    for (auto &x : cn)
    {
      x.second = cnter;
      cnter++;
    }
    REP(i, n)
    {
      get<0>(inputs[i]) = cn[get<0>(inputs[i])];
      swap(get<0>(inputs[i]), get<1>(inputs[i]));
    }
  }

  int ans = 0;
  REP(i, n)
  {
    REP(q, n)
    {
      X_line[q].clear();
      Y_line[q].clear();
    }
    REP(q, n)
    {
      if (i == q)
        continue;
      X_line[get<0>(inputs[q])].insert({get<1>(inputs[q]), get<2>(inputs[q])});
      Y_line[get<1>(inputs[q])].insert({get<0>(inputs[q]), get<2>(inputs[q])});
    }
    int cnt = 1;
    tuple<int, int, int> now = inputs[i];
    while (true)
    {
      tuple<int, int, int> next;
      if (get<2>(now) == 0)
      {
        // move x -> plus
        auto x = Y_line[get<1>(now)].lower_bound({get<0>(now), -1});
        if (x == Y_line[get<1>(now)].end())
        {
          break;
        }
        next = {(*x).first, get<1>(now), (*x).second};
      }
      else if (get<2>(now) == 2)
      {
        // move x -> minus
        auto x = Y_line[get<1>(now)].lower_bound({get<0>(now), -1});
        if (x == Y_line[get<1>(now)].begin())
        {
          break;
        }
        x--;
        next = {(*x).first, get<1>(now), (*x).second};
      }
      else if (get<2>(now) == 1)
      {
        // move y -> plus
        auto x = X_line[get<0>(now)].lower_bound({get<1>(now), -1});
        if (x == X_line[get<0>(now)].end())
        {
          break;
        }
        next = {get<0>(now), (*x).first, (*x).second};
      }
      else
      {
        // move y -> minus
        auto x = X_line[get<0>(now)].lower_bound({get<1>(now), -1});
        if (x == X_line[get<0>(now)].begin())
        {
          break;
        }
        x--;
        next = {get<0>(now), (*x).first, (*x).second};
      }

      X_line[get<0>(next)].erase({get<1>(next), get<2>(next)});
      Y_line[get<1>(next)].erase({get<0>(next), get<2>(next)});
      now = next;
      cnt++;
    }
    ans = max(ans, cnt);
  }
  cout << ans << endl;
}
#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(100);
  // scanf/printf user should delete this fasterize input/output script

  int t = 1;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 1450
memory_kb: 4240
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

template <typename T> std::map<T, int> compress(std::vector<T>& v) {
    std::sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    std::map<T, int> res;
    for (size_t i = 0; i < v.size(); i++) res[v[i]] = i;
    return res;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<int> x(n), y(n);
    vector<char> d(n);
    for (int i = 0; i < n; i++) cin >> y[i] >> x[i] >> d[i];

    vector<int> cx = x, cy = y;
    map<int, int> mpx = compress(cx), mpy = compress(cy);
    for (int i = 0; i < n; i++) x[i] = mpx[x[i]], y[i] = mpy[y[i]];
    int N = mpx.size(), M = mpy.size();

    auto ctoi = [](char c) {
        if (c == 'v') return 0;
        if (c == '>') return 1;
        if (c == '^') return 2;
        return 3;
    };
    auto move = [&](int cur, vector<set<pair<int, int>>>& X, vector<set<pair<int, int>>>& Y) {
        int dir = ctoi(d[cur]), a = x[cur], b = y[cur];
        X[a].erase({b, cur});
        Y[b].erase({a, cur});
        if (!(dir & 1)) {
            auto itr = Y[b].upper_bound({a, n});
            if (dir == 0) {
                if (itr == Y[b].end()) return -1;
                return itr->second;
            } else {
                if (itr == Y[b].begin()) return -1;
                return (--itr)->second;
            }
        } else {
            auto itr = X[a].upper_bound({b, n});
            if (dir == 1) {
                if (itr == X[a].end()) return -1;
                return itr->second;
            } else {
                if (itr == X[a].begin()) return -1;
                return (--itr)->second;
            }
        }
    };

    int ans = 0;
    for (int i = 0; i < n; i++) {
        vector<set<pair<int, int>>> X(N), Y(M);
        for (int j = 0; j < n; j++) {
            X[x[j]].emplace(y[j], j);
            Y[y[j]].emplace(x[j], j);
        }
        int cnt = 1, cur = i;
        while (1) {
            int nxt = move(cur, X, Y);
            if (nxt < 0) break;
            cnt++;
            swap(cur, nxt);
        }
        ans = max(ans, cnt);
    }

    cout << ans << '\n';
    return 0;
}
accuracy: 1
time_ms: 1520
memory_kb: 4060
final_rank: 12

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

#include <algorithm>
#include <map>
#include <vector>

template <typename T> std::map<T, int> compress(std::vector<T>& v) {
    std::sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    std::map<T, int> res;
    for (size_t i = 0; i < v.size(); i++) res[v[i]] = i;
    return res;
}

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<int> x(n), y(n);
    vector<char> d(n);
    for (int i = 0; i < n; i++) cin >> y[i] >> x[i] >> d[i];

    vector<int> cx = x, cy = y;
    map<int, int> mpx = compress(cx), mpy = compress(cy);
    for (int i = 0; i < n; i++) x[i] = mpx[x[i]], y[i] = mpy[y[i]];
    int N = mpx.size(), M = mpy.size();

    auto ctoi = [](char c) {
        if (c == 'v') return 0;
        if (c == '>') return 1;
        if (c == '^') return 2;
        return 3;
    };
    auto move = [&](int cur, vector<set<pair<int, int>>>& X, vector<set<pair<int, int>>>& Y) {
        int dir = ctoi(d[cur]), a = x[cur], b = y[cur];
        X[a].erase({b, cur});
        Y[b].erase({a, cur});
        if (!(dir & 1)) {
            auto itr = Y[b].upper_bound({a, n});
            if (dir == 0) {
                if (itr == Y[b].end()) return -1;
                return itr->second;
            } else {
                if (itr == Y[b].begin()) return -1;
                return (--itr)->second;
            }
        } else {
            auto itr = X[a].upper_bound({b, n});
            if (dir == 1) {
                if (itr == X[a].end()) return -1;
                return itr->second;
            } else {
                if (itr == X[a].begin()) return -1;
                return (--itr)->second;
            }
        }
    };

    int ans = 0;
    for (int i = 0; i < n; i++) {
        vector<set<pair<int, int>>> X(N), Y(M);
        for (int j = 0; j < n; j++) {
            X[x[j]].emplace(y[j], j);
            Y[y[j]].emplace(x[j], j);
        }
        int cnt = 1, cur = i;
        while (1) {
            int nxt = move(cur, X, Y);
            if (nxt < 0) break;
            cnt++;
            swap(cur, nxt);
        }
        ans = max(ans, cnt);
    }

    cout << ans << '\n';
    return 0;
}
accuracy: 1
time_ms: 1560
memory_kb: 4064
final_rank: 14

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
//const int mod = 1e9 + 7;
const int mod = 998244353;

int main(){
    int n; cin >> n;
    vl x(n),y(n);
    vc c(n);
    rep(i,n) cin >> x[i] >> y[i] >> c[i];
    map<ll,set<P>> initX;
    map<ll,set<P>> initY;
    rep(i,n){
        initX[x[i]].emplace(y[i],i);
        initY[y[i]].emplace(x[i],i);
    }
    int ans = 1;
    rep(s,n){
        auto X = initX;
        auto Y = initY;
        int res = 0;
        int now = s;
        while(1){
            res++;
            if(c[now] == '<'){
                auto itr = Y[y[now]].lower_bound(P(x[now],-inf));
                if(itr == Y[y[now]].begin()) break;
                itr--;
                Y[y[now]].erase(P(x[now],now));
                X[x[now]].erase(P(y[now],now));
                now = (*itr).second;
            }else if(c[now] == '>'){
                auto itr = Y[y[now]].upper_bound(P(x[now],inf));
                if(itr == Y[y[now]].end()) break;
                Y[y[now]].erase(P(x[now],now));
                X[x[now]].erase(P(y[now],now));
                now = (*itr).second;
            }else if(c[now] == '^'){
                auto itr = X[x[now]].lower_bound(P(y[now],-inf));
                if(itr == X[x[now]].begin()) break;
                itr--;
                X[x[now]].erase(P(y[now],now));
                Y[y[now]].erase(P(x[now],now));
                now = (*itr).second;
            }else{
                auto itr = X[x[now]].upper_bound(P(y[now],inf));
                if(itr == X[x[now]].end()) break;
                X[x[now]].erase(P(y[now],now));
                Y[y[now]].erase(P(x[now],now));
                now = (*itr).second;
            }
        }
        chmax(ans, res);
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 1890
memory_kb: 4780
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
	return (ull)rng() % B;
}

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

int main(){
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	int n; cin >> n;
	vector<int> x(n),y(n),d(n);
	for(int i=0;i<n;i++){
		cin >> y[i] >> x[i];
		char c; cin >> c;
		if(c=='v')d[i]=0;
		else if(c=='>')d[i]=1;
		else if(c=='^')d[i]=2;
		else d[i]=3;
	}
	int h,w;
	{
		auto v=x;
		sort(v.begin(), v.end());
		v.erase(unique(v.begin(), v.end()),v.end());
		for(int i=0;i<n;i++){
			x[i]=lower_bound(v.begin(), v.end(),x[i])-v.begin();
		}
		h=v.size();
		v=y;
		sort(v.begin(), v.end());
		v.erase(unique(v.begin(), v.end()),v.end());
		for(int i=0;i<n;i++){
			y[i]=lower_bound(v.begin(), v.end(),y[i])-v.begin();
		}
		w=v.size();
	}
	vector<vector<int>> di(h,vector<int>(w,-1));
	for(int i=0;i<n;i++)di[x[i]][y[i]]=d[i];
	auto cal=[&](int sx,int sy)->int{
		int res=0;
		vector<vector<bool>> used(h,vector<bool>(w,false));
		while(1){
			res++;
			int i=di[sx][sy];
			used[sx][sy]=true;
			while(1){
				sx+=dx[i],sy+=dy[i];
				if(0<=sx and sx<h and 0<=sy and sy<w){
					if(di[sx][sy]!=-1 and !used[sx][sy])break;
				}
				else return res;
			}
		}
		return 0;
	};
	int res=0;
	for(int i=0;i<n;i++){
		res=max(res,cal(x[i],y[i]));
	}
	printf("%d\n",res);
}
accuracy: 1
time_ms: 740
memory_kb: 12108
final_rank: 19

code_snippet: #define NDEBUG
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> P;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}
template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;
template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const multiset<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------ End of template --------------

#define endl "\n"

void solve() {
  int n;
  cin >> n;
  vector<int> x(n), y(n);
  vector<char> d(n);
  rep(i, n) cin >> x[i] >> y[i] >> d[i];

  vector<int> zip;
  rep(i, n) {
    zip.push_back(x[i]);
    zip.push_back(y[i]);
  }
  sort(all(zip));
  zip.erase(unique(all(zip)), zip.end());
  rep(i, n) {
    x[i] = lower_bound(all(zip), x[i]) - zip.begin();
    y[i] = lower_bound(all(zip), y[i]) - zip.begin();
  }

  auto ds = vect(zip.size(), vect(zip.size(), '-'));
  rep(i, n) ds[x[i]][y[i]] = d[i];

  int ans = 0;
  for (int i = 0; i < n; i++) {
    int res = 0;
    int cx = x[i], cy = y[i];
    vector<set<int>> xs(zip.size()), ys(zip.size());
    rep(j, n) {
      xs[x[j]].insert(y[j]);
      ys[y[j]].insert(x[j]);
    }
    while (1) {
      res++;
      xs[cx].erase(cy);
      ys[cy].erase(cx);
      if (ds[cx][cy] == 'v') {
        auto it = xs[cx].lower_bound(cy);
        if (it == xs[cx].end()) break;
        cy = *it;
      } else if (ds[cx][cy] == '>') {
        auto it = ys[cy].lower_bound(cx);
        if (it == ys[cy].end()) break;
        cx = *it;
      } else if (ds[cx][cy] == '^') {
        auto it = xs[cx].lower_bound(cy);
        if (it == xs[cx].begin()) break;
        cy = *(--it);
      } else {
        auto it = ys[cy].lower_bound(cx);
        if (it == ys[cy].begin()) break;
        cx = *(--it);
      }
    }
    chmax(ans, res);
  }

  cout << ans << endl;

  return;
}

int main() {
  fastio();
  solve();
  // int t;
  // cin >> t;
  // while (t--) solve();

  // int t; cin >> t;
  // for(int i=1;i<=t;i++){
  //   cout << "Case #" << i << ": ";
  //   solve();
  // }
  return 0;
}
accuracy: 1
time_ms: 1620
memory_kb: 12972
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

int x[3000], y[3000];
string d[3000];
set<PII> X[3000], Y[3000];
int main() {
    int n;
    cin >> n;
    vector<int> vx, vy;
    for (int i = 0; i < n; i++) {
        cin >> x[i] >> y[i] >> d[i];
        vx.push_back(x[i]);
        vy.push_back(y[i]);
    }
    sort(ALL(vx));
    sort(ALL(vy));
    vx.erase(unique(ALL(vx)), vx.end());
    vy.erase(unique(ALL(vy)), vy.end());
    for (int i = 0; i < n; i++) {
        x[i] = lower_bound(ALL(vx), x[i]) - vx.begin();
        y[i] = lower_bound(ALL(vy), y[i]) - vy.begin();
    }
    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < vx.size(); j++)
            X[j].clear();
        for (int j = 0; j < vy.size(); j++)
            Y[j].clear();
        for (int j = 0; j < n; j++) {
            if (j == i)
                continue;
            X[x[j]].emplace(y[j], j);
            Y[y[j]].emplace(x[j], j);
        }
        int cnt = 1;
        int now = i;
        while (1) {
            if (d[now] == ">") {
                auto itr = Y[y[now]].lower_bound(PII(x[now], -1));
                if (itr == Y[y[now]].end())
                    break;
                PII p = *itr;
                Y[y[now]].erase(p);
                X[p.first].erase(PII(y[now], p.second));
                now = p.second;
            } else if (d[now] == "<") {
                auto itr = Y[y[now]].lower_bound(PII(x[now], -1));
                if (Y[y[now]].empty() || itr == Y[y[now]].begin())
                    break;
                itr--;
                PII p = *itr;
                Y[y[now]].erase(p);
                X[p.first].erase(PII(y[now], p.second));
                now = p.second;
            } else if (d[now] == "v") {
                auto itr = X[x[now]].lower_bound(PII(y[now], -1));
                if (itr == X[x[now]].end())
                    break;
                PII p = *itr;
                X[x[now]].erase(p);
                Y[p.first].erase(PII(x[now], p.second));
                now = p.second;
            } else {
                auto itr = X[x[now]].lower_bound(PII(y[now], -1));
                if (X[x[now]].empty() || itr == X[x[now]].begin())
                    break;
                itr--;
                PII p = *itr;
                X[x[now]].erase(p);
                Y[p.first].erase(PII(x[now], p.second));
                now = p.second;
            }
            cnt++;
        }
        ans = max(ans, cnt);
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 1470
memory_kb: 4268
final_rank: 13

code_snippet: #include<iostream>
#include<map>
#include<algorithm>
#include<vector>
using namespace std;
int N;
int X[3000],Y[3000];
char D[3000];
int nxt[3000][4];
map<int,vector<pair<int,int> > >mX,mY;
main()
{
	cin>>N;
	for(int i=0;i<N;i++)
	{
		cin>>X[i]>>Y[i]>>D[i];
		mX[X[i]].push_back(make_pair(Y[i],i));
		mY[Y[i]].push_back(make_pair(X[i],i));
	}
	for(map<int,vector<pair<int,int> > >::iterator it=mX.begin();it!=mX.end();it++)
	{
		sort(it->second.begin(),it->second.end());
	}
	for(map<int,vector<pair<int,int> > >::iterator it=mY.begin();it!=mY.end();it++)
	{
		sort(it->second.begin(),it->second.end());
	}
	int ans=0;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)for(int k=0;k<4;k++)nxt[j][k]=-1;
		for(pair<int,vector<pair<int,int> > >mx:mX)
		{
			for(int j=1;j<mx.second.size();j++)
			{
				nxt[mx.second[j-1].second][0]=mx.second[j].second;
				nxt[mx.second[j].second][2]=mx.second[j-1].second;
			}
		}
		for(pair<int,vector<pair<int,int> > >my:mY)
		{
			for(int j=1;j<my.second.size();j++)
			{
				nxt[my.second[j-1].second][1]=my.second[j].second;
				nxt[my.second[j].second][3]=my.second[j-1].second;
			}
		}
		int cnt=0,id=i;
		while(id>=0)
		{
			{
				int U=nxt[id][0],D=nxt[id][2];
				if(U>=0)nxt[U][2]=D;
				if(D>=0)nxt[D][0]=U;
				int R=nxt[id][1],L=nxt[id][3];
				if(R>=0)nxt[R][3]=L;
				if(L>=0)nxt[L][1]=R;
			}
			cnt++;
			if(D[id]=='v')id=nxt[id][0];
			else if(D[id]=='>')id=nxt[id][1];
			else if(D[id]=='^')id=nxt[id][2];
			else id=nxt[id][3];
		}
		ans=max(ans,cnt);
	}
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 370
memory_kb: 3536
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
int main(){
  int n;
  cin >> n;
  vector<int> x(n), y(n);
  vector<char> d(n);
  for (int i = 0; i < n; i++){
    cin >> x[i] >> y[i] >> d[i];
  }
  map<int, vector<pair<int, int>>> H;
  for (int i = 0; i < n; i++){
    H[y[i]].push_back(make_pair(x[i], i));
  }
  map<int, vector<pair<int, int>>> V;
  for (int i = 0; i < n; i++){
    V[x[i]].push_back(make_pair(y[i], i));
  }
  vector<int> L(n, -1), R(n, -1);
  for (auto P : H){
    sort(P.second.begin(), P.second.end());
    int cnt = P.second.size();
    for (int i = 0; i < cnt - 1; i++){
      int a = P.second[i].second;
      int b = P.second[i + 1].second;
      R[a] = b;
      L[b] = a;
    }
  }
  vector<int> U(n, -1), D(n, -1);
  for (auto P : V){
    sort(P.second.begin(), P.second.end());
    int cnt = P.second.size();
    for (int i = 0; i < cnt - 1; i++){
      int a = P.second[i].second;
      int b = P.second[i + 1].second;
      D[a] = b;
      U[b] = a;
    }
  }
  int ans = 0;
  for (int i = 0; i < n; i++){
    vector<int> L2 = L, R2 = R, U2 = U, D2 = D;
    int cnt = 0;
    int curr = i;
    while (1){
      cnt++;
      if (L2[curr] != -1){
        R2[L2[curr]] = R2[curr];
      }
      if (R2[curr] != -1){
        L2[R2[curr]] = L2[curr];
      }
      if (U2[curr] != -1){
        D2[U2[curr]] = D2[curr];
      }
      if (D2[curr] != -1){
        U2[D2[curr]] = U2[curr];
      }
      int next;
      if (d[curr] == '>'){
        next = R2[curr];
      }
      if (d[curr] == '<'){
        next = L2[curr];
      }
      if (d[curr] == '^'){
        next = U2[curr];
      }
      if (d[curr] == 'v'){
        next = D2[curr];
      }
      if (next == -1){
        break;
      } else {
        curr = next;
      }
    }
    ans = max(ans, cnt);
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 3652
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

const long double EPS = 1e-10;
const long long INF = 1e18;
const long double PI = acos(-1.0L);
//const ll mod = 1000000007;
ll x[3005], y[3005];
char d[3005];
bool visited[3005];
set<i_i> row[3005], column[3005];
ll N;
ll ans = -INF;
void initialize() {
    for(int i = 0; i < N; i++) {
        visited[i] = false;
        row[i].clear();
        column[i].clear();
    }
    for(int i = 0; i < N; i++) {
        row[x[i]].insert({y[i], i});
        column[y[i]].insert({x[i], i});
    }
}

int g(int now) {
    int ret = -1;
    if(d[now] == '^') {
        auto itr = row[x[now]].lower_bound({y[now], -INF});
        if(itr == row[x[now]].begin()) return -1;
        itr--;
        ret = (*itr).second;
        row[x[now]].erase(itr);
    }
    if(d[now] == 'v') {
        auto itr = row[x[now]].lower_bound({y[now], -INF});
        if(itr == row[x[now]].end()) return -1;
        ret = (*itr).second;
        row[x[now]].erase(itr);
    }
    if(d[now] == '<') {
        auto itr = column[y[now]].lower_bound({x[now], -INF});
        if(itr == column[y[now]].begin()) return -1;
        itr--;
        ret = (*itr).second;
        column[y[now]].erase(itr);
    }
    if(d[now] == '>') {
        auto itr = column[y[now]].lower_bound({x[now], -INF});
        if(itr == column[y[now]].end()) return -1;
        ret = (*itr).second;
        column[y[now]].erase(itr);
    }
    return ret;
}

void f(int s) {
    //cerr << "-------" << s << "--------" << endl;
    int now = s;
    ll tmpans = 1;
    initialize();
    visited[s] = true;
    while(true) {
        //cerr << now << endl;
        int nxt = g(now);
        if(nxt == -1) break;
        if(visited[nxt]) continue;
        visited[nxt] = true;
        tmpans++;
        now = nxt;
    }
    chmax(ans, tmpans);
}

int main() {
    cin >> N;
    vector<ll> cmpx, cmpy;
    for(int i = 0; i < N; i++) {
        cin >> x[i] >> y[i] >> d[i];
        cmpx.push_back(x[i]);
        cmpy.push_back(y[i]);
    }
    sort(cmpx.begin(), cmpx.end());
    cmpx.erase(unique(cmpx.begin(), cmpx.end()), cmpx.end());
    sort(cmpy.begin(), cmpy.end());
    cmpy.erase(unique(cmpy.begin(), cmpy.end()), cmpy.end());
    for(int i = 0; i < N; i++) {
        auto itr = lower_bound(cmpx.begin(), cmpx.end(), x[i]);
        x[i] = itr - cmpx.begin();
        itr = lower_bound(cmpy.begin(), cmpy.end(), y[i]);
        y[i] = itr - cmpy.begin();
    }
    for(int i = 0; i < N; i++) {
        f(i);
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 1230
memory_kb: 4112
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=3005,INF=1<<30;
set<pair<int,int>> X[MAX],Y[MAX];

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int N;cin>>N;
    map<int,int> mx,my;
    mx[-INF]=1;
    mx[INF]=1;
    my[-INF]=1;
    my[INF]=1;
    vector<int> x(N),y(N),dir(N);
    for(int i=0;i<N;i++){
        cin>>x[i]>>y[i];
        mx[x[i]]=1;
        my[y[i]]=1;
        char c;cin>>c;
        if(c=='^') dir[i]=0;
        if(c=='v') dir[i]=1;
        if(c=='>') dir[i]=2;
        if(c=='<') dir[i]=3;
    }
    
    int idx=0,idy=0;
    for(auto &a:mx){
        a.se=idx;
        idx++;
    }
    for(auto &a:my){
        a.se=idy;
        idy++;
    }
    
    for(int i=0;i<N;i++){
        x[i]=mx[x[i]];
        y[i]=my[y[i]];
    }
    
    int ans=0;
    
    for(int s=0;s<N;s++){
        for(int i=0;i<N;i++){
            X[x[i]].insert(mp(y[i],i));
            Y[y[i]].insert(mp(x[i],i));
            
            X[x[i]].insert(mp(0,-1));
            X[x[i]].insert(mp(idy-1,-1));
            Y[y[i]].insert(mp(0,-1));
            Y[y[i]].insert(mp(idx-1,-1));
        }
        
        int cnt=0;
        int now=s;
        X[x[now]].erase(mp(y[now],now));
        Y[y[now]].erase(mp(x[now],now));
        
        while(1){
            if(now==-1) break;
            
            cnt++;
            
            if(dir[now]==0){
                auto it=X[x[now]].lower_bound(mp(y[now],now));
                it--;
                X[x[now]].erase(it);
                Y[(*it).fi].erase(mp(x[now],(*it).se));
                now=(*it).se;
            }else if(dir[now]==1){
                auto it=X[x[now]].lower_bound(mp(y[now],now));
                X[x[now]].erase(it);
                Y[(*it).fi].erase(mp(x[now],(*it).se));
                now=(*it).se;
            }else if(dir[now]==2){
                auto it=Y[y[now]].lower_bound(mp(x[now],now));
                Y[y[now]].erase(it);
                X[(*it).fi].erase(mp(y[now],(*it).se));
                now=(*it).se;
            }else{
                auto it=Y[y[now]].lower_bound(mp(x[now],now));
                it--;
                Y[y[now]].erase(it);
                X[(*it).fi].erase(mp(y[now],(*it).se));
                now=(*it).se;
            }
            
        }
        
        chmax(ans,cnt);
    }
    
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 1940
memory_kb: 4204
final_rank: 15

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

int func(vector<set<pair<int, int>>>xs, vector<set<pair<int, int>>>ys, vector<int>&x, vector<int>&y, vector<char>&c, int st) {
	int cx = x[st], cy = y[st];
	int ret = 1;
	xs[cx].erase(xs[cx].lower_bound({ cy,0 }));
	ys[cy].erase(ys[cy].lower_bound({ cx,0 }));
	char nx = c[st];
	while (ret < N) {
		if (nx == '^') {
			auto it = xs[cx].lower_bound({ cy,0 });
			if (xs[cx].begin() == it)break;
			it = prev(it);
			ret++;
			cy = it->first;
			nx = c[it->second];
		}
		else if (nx == '<') {
			auto it = ys[cy].lower_bound({ cx,0 });
			if (ys[cy].begin() == it)break;
			it = prev(it);
			ret++;
			cx = it->first;
			nx = c[it->second];
		}
		else if (nx == 'v') {
			auto it = xs[cx].lower_bound({ cy,0 });
			if (xs[cx].end() == it)break;
			ret++;
			cy = it->first;
			nx = c[it->second];
		}
		else {
			auto it = ys[cy].lower_bound({ cx,0 });
			if (ys[cy].end() == it)break;
			ret++;
			cx = it->first;
			nx = c[it->second];
		}
		xs[cx].erase(xs[cx].lower_bound({ cy,0 }));
		ys[cy].erase(ys[cy].lower_bound({ cx,0 }));
	}
	return ret;
}

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

	cin >> N;
	vector<int>x(N);
	vector<int>y(N);
	vector<char>c(N);
	map<int, int>xp;
	map<int, int>yp;
	for (int i = 0; i < N; i++) {
		cin >> x[i] >> y[i] >> c[i];
		xp[x[i]] = 0;
		yp[y[i]] = 0;
	}
	int cnt = 0;
	for (auto &i : xp) {
		i.second = cnt++;
	}
	cnt = 0;
	for (auto &i : yp) {
		i.second = cnt++;
	}
	vector<set<pair<int, int>>>xx(xp.size());
	vector<set<pair<int, int>>>yy(yp.size());
	for (int i = 0; i < N; i++) {
		x[i] = xp[x[i]];
		y[i] = yp[y[i]];
		xx[x[i]].insert({ y[i],i });
		yy[y[i]].insert({ x[i],i });
	}
	int ans = 0;
	for (int i = 0; i < N; i++) {
		ans = max(ans, func(xx, yy, x, y, c, i));
	//	cout << i << " " << ans << endl;
	}
	cout << ans << endl;
}
accuracy: 1
time_ms: 1240
memory_kb: 3908
final_rank: 6