Problem:
Problem G: Get Lost
ICPC World Finals 5日目
ティー氏はR国の街で迷ってしまった。
困ったことに、街並みが似ているため、自分が今どこにいるかが全く分からない。
R国は「おそろしあ」であるから、敵に襲撃される前にホテルへ戻らねばならない。 幸い、どのように曲がって来たかだけは覚えているので、
行き当たりばったりに進んでみよう。
問題
\( w \times h \)マスの二次元格子状のマップがある。 左上のマスの座標を\(
(1, 1) \)、右下のマスの座標を\( (w, h) \)とする。 マップの周りは壁で囲まれており、
\(n\)個の障害物が座標\( (x_{i}, y_{i}) (1 \leq i \leq n) \)に置かれている。
さらに、命令列\( r_{1}r_{2} \cdots r_{m} \)と目的座標\( (g_{x}, g_{y})
\)が与えられる。 開始座標と進行方向の設定後、歩行者は以下の移動規則に従って歩行を開始する。
1. カウンタを\( i=1
\)に初期化し、開始座標と進行方向（上・下・左・右）を設定する。
2. 壁・障害物に出会うまで直進する。
3. 壁・障害物の手前で次のいずれかを実行する。
3. a. \( i>m \)、すなわち命令が無ければ歩行を終了する。
3. b. 命令\( r_{i} \)がLならば左、Rならば右へ方向転換する。
4. \( i \)をインクリメントする。
5. 2.に戻る。
歩行開始から歩行終了までに通過した座標（開始座標を含む）に目的座標\( (g_{x},
g_{y}) \)が含まれれば、歩行者が目的地に辿り着いたと解釈する。
目的地に辿り着くことのできる開始座標・進行方向の組み合わせは何通りあるかを求めよ。
ただし、開始座標には障害物やマップ外の座標を設定することはできないとする。 （目的座標を設定することはできる。）
入力
w h g
x
g
y
n
x
1
y
1
…
x
n
y
n
r
1
r
2
… r
m
1行目に マップの横幅\(w\)、縦幅\(h\)、目的地のx座標\( g_{x} \)、目的地のy座標\( g_{y}
\)、障害物の数\(n\)が空白区切りで与えられる。 2行目から\( n+1 \)行目に 各障害物の座標\( (x_{i},
y_{i}) \)が空白区切りで与えられる。 \( n+2 \)行目に長さ\(m\)の命令列\( r_{1}r_{2} \cdots
r_{m} \)が与えられる。
出力
目的地に辿り着けるような 開始座標・進行方向の組み合わせの数を1行に出力せよ。
制約
入力は全て整数である
\( 2 \leq w, h \leq 10^{5}(= 100000) \)
\( 0 \leq n \leq 10^{5}(= 100000) \)
\( 1 \leq g_{x}, x_{i} \leq w \)
\( 1 \leq g_{y}, y_{i} \leq h \)
\( (x_{i}, y_{i}) \not = (g_{x}, g_{y}) (1 \leq i \leq n)
\)
\( (x_{i}, y_{i}) \not = (x_{j}, y_{j}) (i \not = j) \)
\( r_{i} \in \{ L, R \} (1 \leq i \leq m) \)
\( 1 \leq m \leq 20 \)
入出力例
入力1
3 3 3 2 2
1 1
2 2
RL
出力1
9
以下の5通りの歩行に加え、 目的座標を開始座標とする歩行（4通り）が目的座標を通過する。
入力2
4 4 3 1 4
1 1
3 2
1 3
4 3
RR
出力2
13
以下の開始座標・進行方向から開始する歩行は目的座標を通過する。
入力3
100000 100000 46597 49716 17
38713 77141
46598 78075
66177 49715
58569 77142
48303 12742
32829 65105
32830 78076
70273 27408
48302 21196
27119 54458
38714 65104
46598 54457
27118 12743
60242 21197
60241 1101
58568 27409
93581 1100
LLRRLLLLRRLL
出力3
647505

Submitted solutions:

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

using lli = long long;
using P = pair<lli, lli>;

constexpr lli MAX = 100000;

lli w, h, gx, gy, n;
vector<P> input;
vector<lli> vec[4][MAX + 1]; //(x, y)
string r;

bool check(lli x, lli y, lli d) {
    for (size_t i = 0; i <= r.size(); i++) {
        lli nx, ny;
        if (d == 0) {
            nx = x;
            ny = *lower_bound(vec[0][x].begin(), vec[0][x].end(), -y);
            ny = -ny;
            if (nx == gx && ny == gy) return true;
            ny = ny + 1;
            if (nx == gx && ny <= gy && gy <= y) return true;
        }
        if (d == 1) {
            nx = *lower_bound(vec[1][y].begin(), vec[1][y].end(), x);
            ny = y;
            if (nx == gx && ny == gy) return true;
            nx = nx - 1;
            if (x <= gx && gx <= nx && ny == gy) return true;
        }
        if (d == 2) {
            nx = x;
            ny = *lower_bound(vec[2][x].begin(), vec[2][x].end(), y);
            if (nx == gx && ny == gy) return true;
            ny = ny - 1;
            if (nx == gx && y <= gy && gy <= ny) return true;
        }
        if (d == 3) {
            nx = *lower_bound(vec[3][y].begin(), vec[3][y].end(), -x);
            ny = y;
            nx = -nx;
            if (nx == gx && ny == gy) return true;
            nx = nx + 1;
            if (nx <= gx && gx <= x && ny == gy) return true;
        }
        x = nx;
        y = ny;
        if (i == r.size()) break;
        if (r[i] == 'R') d = (d + 1) % 4;
        else d = (d - 1 + 4) % 4;
    }
    return false;
}

lli solve() {
    lli res = 0;
    for (lli i = 0; i <= MAX; i++) {
        for (int j = 0; j < 4; j++) vec[j][i].clear();
    }
    for (auto [x, y] : input) {
        vec[1][y].push_back(x);
        vec[3][y].push_back(x);
    }
    vec[1][gy].push_back(gx);
    vec[3][gy].push_back(gx);
    for (auto [x, y] : input) {
        vec[0][x].push_back(y);
        vec[2][x].push_back(y);
    }
    vec[0][gx].push_back(gy);
    vec[2][gx].push_back(gy);
    for (lli i = 0; i < 4; i++) {
        for (lli j = 1; j <= MAX; j++) {
            vec[i][j].push_back(0);
            vec[i][j].push_back((i % 2 == 0 ? h : w) + 1);
        }
    }
    for (lli i = 0; i <= MAX; i++) {
        for (auto &val : vec[0][i]) val = -val;
        for (auto &val : vec[3][i]) val = -val;
    }
    for (lli i = 0; i <= MAX; i++) {
        for (int j = 0; j < 4; j++) {
            if (!vec[j][i].empty()) sort(vec[j][i].begin(), vec[j][i].end());
        }
    }
    for (lli d = 0; d < 4; d++) {
        lli upper = (d % 2 == 0 ? w : h);
        for (lli i = 1; i <= upper; i++) {
            for (size_t j = 1; j < vec[d][i].size(); j++) {
                if (d % 2 == 1) {
                    lli sx = vec[d][i][j] - 1;
                    if (d == 3) sx = -sx;
                    if (sx <= 0 || sx > w) continue;
                    if (vec[d][i][j] - vec[d][i][j - 1] - 1 > 0 && check(sx, i, d)) {
                        res += vec[d][i][j] - vec[d][i][j - 1] - 1;
                    }
                }
                if (d % 2 == 0) {
                    lli sy = vec[d][i][j] - 1;
                    if (d == 0) sy = -sy;
                    if (sy <= 0 || sy > h) continue;
                    if (vec[d][i][j] - vec[d][i][j - 1] - 1 > 0 && check(i, sy, d)) {
                        res += vec[d][i][j] - vec[d][i][j - 1] - 1;
                    }
                }
            }
        }
    }
    return res;
}

int main() {
    cin >> w >> h >> gx >> gy >> n;
    input.reserve(n);
    for (lli i = 0; i < n; i++) {
        lli x, y;
        cin >> x >> y;
        input.emplace_back(x, y);
    }
    cin >> r;
    cout << solve() + 4 << endl;
    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 32304
final_rank: 1

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

using ll = long long;

// dirs: 0=RIGHT, 1=DOWN, 2=LEFT, 3=UP
int left_turn(int d){ return (d+3)&3; }
int right_turn(int d){ return (d+1)&3; }
int inv_turn(int d_out, char r){ // incoming dir before turn
    return (r=='L') ? right_turn(d_out) : left_turn(d_out);
}

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

    int w,h,gx,gy,n;
    if(!(cin>>w>>h>>gx>>gy>>n)) return 0;
    vector<pair<int,int>> obs(n);
    for(auto &p: obs) cin>>p.first>>p.second;
    string R; cin>>R;
    int m = (int)R.size();

    // rowBlocks[y]: sorted blocked x in row y (with walls 0 and w+1)
    // colBlocks[x]: sorted blocked y in col x (with walls 0 and h+1)
    vector<vector<int>> rowBlocks(h+1), colBlocks(w+1);
    for(auto [x,y]: obs){
        rowBlocks[y].push_back(x);
        colBlocks[x].push_back(y);
    }
    for(int y=1;y<=h;y++){
        auto &v=rowBlocks[y];
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        v.insert(v.begin(),0);
        v.push_back(w+1);
    }
    for(int x=1;x<=w;x++){
        auto &v=colBlocks[x];
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        v.insert(v.begin(),0);
        v.push_back(h+1);
    }
    auto prev_blocked_row = [&](int y,int x){
        auto &v=rowBlocks[y];
        int i = int(lower_bound(v.begin(),v.end(),x) - v.begin());
        return v[i-1];
    };
    auto next_blocked_row = [&](int y,int x){
        auto &v=rowBlocks[y];
        int i = int(upper_bound(v.begin(),v.end(),x) - v.begin());
        return v[i];
    };
    auto prev_blocked_col = [&](int x,int y){
        auto &v=colBlocks[x];
        int i = int(lower_bound(v.begin(),v.end(),y) - v.begin());
        return v[i-1];
    };
    auto next_blocked_col = [&](int x,int y){
        auto &v=colBlocks[x];
        int i = int(upper_bound(v.begin(),v.end(),y) - v.begin());
        return v[i];
    };
    auto is_valid_stop = [&](int x,int y,int d)->bool{
        if(d==0) return next_blocked_row(y,x)==x+1;    // RIGHT
        if(d==2) return prev_blocked_row(y,x)==x-1;    // LEFT
        if(d==1) return next_blocked_col(x,y)==y+1;    // DOWN
        if(d==3) return prev_blocked_col(x,y)==y-1;    // UP
        return false;
    };

    // stop-cell maps for fast range enumeration
    // up[y]   : list of x where (x,y) has blocked at y-1 (incoming UP)
    // down[y] : list of x where (x,y) has blocked at y+1 (incoming DOWN)
    // left[x] : list of y where (x,y) has blocked at x-1 (incoming LEFT)
    // right[x]: list of y where (x,y) has blocked at x+1 (incoming RIGHT)
    vector<vector<int>> up(h+1), down(h+1), lefts(w+1), rights(w+1);
    for(int x=1;x<=w;x++){
        for(int b: colBlocks[x]){
            int yu=b+1; if(1<=yu && yu<=h) up[yu].push_back(x);
            int yd=b-1; if(1<=yd && yd<=h) down[yd].push_back(x);
        }
    }
    for(int y=1;y<=h;y++){
        for(int b: rowBlocks[y]){
            int xl=b+1; if(1<=xl && xl<=w) lefts[xl].push_back(y);
            int xr=b-1; if(1<=xr && xr<=w) rights[xr].push_back(y);
        }
    }
    for(int y=1;y<=h;y++){ sort(up[y].begin(),up[y].end()); sort(down[y].begin(),down[y].end()); }
    for(int x=1;x<=w;x++){ sort(lefts[x].begin(),lefts[x].end()); sort(rights[x].begin(),rights[x].end()); }

    auto enum_row = [&](int y,int xL,int xR,int incoming_dir, vector<pair<int,int>>& out){
        if(xL>xR) return;
        const vector<int>* lst = (incoming_dir==3 ? &up[y] : &down[y]); // UP or DOWN
        auto itL = lower_bound(lst->begin(), lst->end(), xL);
        auto itR = upper_bound(lst->begin(), lst->end(), xR);
        for(auto it=itL; it!=itR; ++it) out.emplace_back(*it, y);
    };
    auto enum_col = [&](int x,int yL,int yR,int incoming_dir, vector<pair<int,int>>& out){
        if(yL>yR) return;
        const vector<int>* lst = (incoming_dir==2 ? &lefts[x] : &rights[x]); // LEFT or RIGHT
        auto itL = lower_bound(lst->begin(), lst->end(), yL);
        auto itR = upper_bound(lst->begin(), lst->end(), yR);
        for(auto it=itL; it!=itR; ++it) out.emplace_back(x, *it);
    };

    // pass-now counts around g (включая старт в самой клетке g)
    auto &rb = rowBlocks[gy];
    int irow = int(lower_bound(rb.begin(),rb.end(),gx) - rb.begin());
    int L = rb[irow-1], Rb = rb[irow];

    auto &cb = colBlocks[gx];
    int icol = int(lower_bound(cb.begin(),cb.end(),gy) - cb.begin());
    int U = cb[icol-1], D = cb[icol];

    long long C_right = gx - L;
    long long C_left  = Rb - gx;
    long long C_up    = gy - U;
    long long C_down  = D  - gy;
    long long P0 = C_right + C_left + C_up + C_down;

    // стоп-клетки, в которые закончится 1-й отрезок, если первый отрезок проходит через g
    pair<int,int> s0_right = {Rb-1, gy};
    pair<int,int> s0_left  = {L+1,  gy};
    pair<int,int> s0_down  = {gx,   D-1};
    pair<int,int> s0_up    = {gx,   U+1};

    array<pair<int,int>,4> s0 = {s0_right, s0_down, s0_left, s0_up}; // index by dir 0..3
    array<long long,4> Cdir = {C_right, C_down, C_left, C_up};

    auto key = [&](int x,int y,int d)->unsigned long long{
        // pack to 64-bit: d(2 bits) | x(20) | y(20)
        return ( (unsigned long long)d<<40 ) | ( (unsigned long long)x<<20 ) | (unsigned long long)y;
    };

    // T_m: стоп-состояния в клетке g
    unordered_set<unsigned long long> Tnext;
    Tnext.reserve(8);
    for(int d=0; d<4; d++){
        if(is_valid_stop(gx,gy,d)) Tnext.insert(key(gx,gy,d));
    }

    // предрасчёт «пассовых» диапазонов для сегмента (k+1): тип и границы
    // d_out=0(R): row gy, x in [L+1, gx]; 2(L): [gx, Rb-1]; 1(D): col gx, y in [U+1, gy]; 3(U): [gy, D-1]
    struct Range { int kind; int fixed; int a,b; }; // kind 0=row,1=col
    array<Range,4> passR = {
        Range{0, gy, L+1, gx},
        Range{1, gx, U+1, gy},
        Range{0, gy, gx,   Rb-1},
        Range{1, gx, gy,   D-1}
    };

    // DP по k=m-1..0
    for(int k=m-1; k>=0; --k){
        char r = R[k];
        unordered_set<unsigned long long> Tcur;
        Tcur.reserve(Tnext.size()*3 + 100);

        // A) сразу проходим через g на следующем отрезке
        for(int d_out=0; d_out<4; ++d_out){
            int d_in = inv_turn(d_out, r);
            auto [kind, fixed, a, b] = passR[d_out];
            vector<pair<int,int>> cells; cells.reserve(64);
            if(kind==0){ // row
                if(a<=b) enum_row(fixed, a, b, d_in, cells);
            }else{
                if(a<=b) enum_col(fixed, a, b, d_in, cells);
            }
            for(auto [x,y]: cells) Tcur.insert(key(x,y,d_in));
        }

        // B) предобразы из Tnext
        for(auto packed : Tnext){
            int d_out = int((packed>>40)&3);
            int x2 = int((packed>>20)&((1u<<20)-1));
            int y2 = int(packed & ((1u<<20)-1));
            int d_in = inv_turn(d_out, r);

            vector<pair<int,int>> cells; cells.reserve(64);
            if(d_out==0){ // RIGHT: назад по строке
                int xL = prev_blocked_row(y2,x2);
                enum_row(y2, xL+1, x2, d_in, cells);
            }else if(d_out==2){ // LEFT
                int xR = next_blocked_row(y2,x2);
                enum_row(y2, x2, xR-1, d_in, cells);
            }else if(d_out==1){ // DOWN
                int yL = prev_blocked_col(x2,y2);
                enum_col(x2, yL+1, y2, d_in, cells);
            }else{ // UP
                int yR = next_blocked_col(x2,y2);
                enum_col(x2, y2, yR-1, d_in, cells);
            }
            for(auto [x,y]: cells) Tcur.insert(key(x,y,d_in));
        }

        Tnext.swap(Tcur);
    }

    // сумма длин первых отрезков для стоп-состояний из T0
    long long sumStops = 0;
    for(auto packed : Tnext){
        int d  = int((packed>>40)&3);
        int x = int((packed>>20)&((1u<<20)-1));
        int y = int(packed & ((1u<<20)-1));
        if(d==0)      sumStops += x - prev_blocked_row(y,x);
        else if(d==2) sumStops += next_blocked_row(y,x) - x;
        else if(d==1) sumStops += y - prev_blocked_col(x,y);
        else          sumStops += next_blocked_col(x,y) - y;
    }

    // пересечение (старты, проходящие через g на первом отрезке, и чьи стопы попали в T0)
    long long overlap = 0;
    for(int d=0; d<4; ++d){
        auto [sx,sy] = s0[d];
        if(Tnext.count( ((unsigned long long)d<<40) | ((unsigned long long)sx<<20) | (unsigned long long)sy ))
            overlap += Cdir[d];
    }

    cout << (sumStops + P0 - overlap) << "\n";
    return 0;
}
accuracy: 0.10714285714285714
time_ms: 10
memory_kb: 25512
final_rank: 5

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

using pii = pair<int,int>;
using ll = long long;
struct PH{ size_t operator()(const pii& p) const noexcept { return (uint64_t)p.first<<32 ^ (uint32_t)p.second; } };
using Iv = pair<int,int>;
using IvMap = unordered_map<int, vector<Iv>>;

static inline void addIv(IvMap& mp,int k,int l,int r){ if(l<=r) mp[k].emplace_back(l,r); }
static inline void sortMerge(vector<Iv>& v){
    if(v.empty()) return;
    sort(v.begin(),v.end());
    int L=v[0].first,R=v[0].second; vector<Iv> t; t.reserve(v.size());
    for(size_t i=1;i<v.size();++i){
        int l=v[i].first,r=v[i].second;
        if(l<=R+1) R=max(R,r); else{ t.emplace_back(L,R); L=l; R=r; }
    }
    t.emplace_back(L,R); v.swap(t);
}
static inline void normalize(IvMap& mp){ for(auto& kv: mp) sortMerge(kv.second); }
static inline bool has(const IvMap& mp,int k,int p){
    auto it=mp.find(k); if(it==mp.end()) return false;
    const auto& v=it->second; int lo=0,hi=(int)v.size()-1;
    while(lo<=hi){ int md=(lo+hi)>>1; if(v[md].first<=p && p<=v[md].second) return true; if(p<v[md].first) hi=md-1; else lo=md+1; }
    return false;
}

int main(){
    ios::sync_with_stdio(false); cin.tie(nullptr);
    int w,h,gx,gy,n; if(!(cin>>w>>h>>gx>>gy>>n)) return 0;
    vector<pii> obs(n); for(int i=0;i<n;++i) cin>>obs[i].first>>obs[i].second;
    string cmd; cin>>cmd; int m=cmd.size();

    unordered_set<pii,PH> blocked; blocked.reserve(n*2+ (w+h)*2);
    for(auto&p:obs) blocked.insert(p);
    auto inB=[&](int x,int y)->bool{ return (x<1||x>w||y<1||y>h)||blocked.count({x,y}); };

    vector<vector<int>> rowB(h+1), colB(w+1);
    for(int y=1;y<=h;++y){ rowB[y].push_back(0); rowB[y].push_back(w+1); }
    for(int x=1;x<=w;++x){ colB[x].push_back(0); colB[x].push_back(h+1); }
    for(auto&p:obs){ rowB[p.second].push_back(p.first); colB[p.first].push_back(p.second); }
    for(int y=1;y<=h;++y){ auto& v=rowB[y]; sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); }
    for(int x=1;x<=w;++x){ auto& v=colB[x]; sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); }

    vector<pii> RB,LB,UB,DB;
    RB.reserve(n+h+10); LB.reserve(n+h+10); UB.reserve(n+w+10); DB.reserve(n+w+10);
    for(int y=1;y<=h;++y){ if(!inB(w,y)) RB.emplace_back(w,y); if(!inB(1,y)) LB.emplace_back(1,y); }
    for(int x=1;x<=w;++x){ if(!inB(x,1)) UB.emplace_back(x,1); if(!inB(x,h)) DB.emplace_back(x,h); }
    for(auto&p:obs){
        int x=p.first,y=p.second;
        if(x>1 && !inB(x-1,y)) RB.emplace_back(x-1,y);
        if(x<w && !inB(x+1,y)) LB.emplace_back(x+1,y);
        if(y>1 && !inB(x,y-1)) DB.emplace_back(x,y-1);
        if(y<h && !inB(x,y+1)) UB.emplace_back(x,y+1);
    }

    auto turnL=[&](int d){ return (d+3)&3; };
    auto turnR=[&](int d){ return (d+1)&3; };

    auto addHits=[&](IvMap& R, IvMap& L, IvMap& U, IvMap& D){
        const auto& r=rowB[gy];
        int ix=lower_bound(r.begin(),r.end(),gx)-r.begin(), rb=r[ix], lb=r[ix-1];
        addIv(R,gy,lb+1,gx); addIv(L,gy,gx,rb-1);
        const auto& c=colB[gx];
        int iy=lower_bound(c.begin(),c.end(),gy)-c.begin(), db=c[iy], ub=c[iy-1];
        addIv(U,gx,gy,db-1); addIv(D,gx,ub+1,gy);
    };

    IvMap R,L,U,D; R.reserve(1024); L.reserve(1024); U.reserve(1024); D.reserve(1024);
    addHits(R,L,U,D); normalize(R); normalize(L); normalize(U); normalize(D);

    for(int i=m-1;i>=0;--i){
        char rc=cmd[i];
        IvMap nR,nL,nU,nD; nR.reserve(R.size()+16); nL.reserve(L.size()+16); nU.reserve(U.size()+16); nD.reserve(D.size()+16);
        addHits(nR,nL,nU,nD);

        int dn;
        for(auto&p:RB){
            int x=p.first,y=p.second; dn=(rc=='L')?turnL(0):turnR(0);
            bool ok = (dn==3?has(U,x,y): dn==1?has(D,x,y): dn==0?has(R,y,x):has(L,y,x));
            if(!ok) continue;
            const auto& v=rowB[y]; int ix=lower_bound(v.begin(),v.end(),x)-v.begin(); int lb=v[ix-1];
            addIv(nR,y,lb+1,x);
        }
        for(auto&p:LB){
            int x=p.first,y=p.second; dn=(rc=='L')?turnL(2):turnR(2);
            bool ok = (dn==3?has(U,x,y): dn==1?has(D,x,y): dn==0?has(R,y,x):has(L,y,x));
            if(!ok) continue;
            const auto& v=rowB[y]; int ix=upper_bound(v.begin(),v.end(),x)-v.begin(); int rb=v[ix];
            addIv(nL,y,x,rb-1);
        }
        for(auto&p:UB){
            int x=p.first,y=p.second; dn=(rc=='L')?turnL(3):turnR(3);
            bool ok = (dn==0?has(R,y,x): dn==2?has(L,y,x): dn==1?has(D,x,y):has(U,x,y));
            if(!ok) continue;
            const auto& v=colB[x]; int iy=upper_bound(v.begin(),v.end(),y)-v.begin(); int db=v[iy];
            addIv(nU,x,y,db-1);
        }
        for(auto&p:DB){
            int x=p.first,y=p.second; dn=(rc=='L')?turnL(1):turnR(1);
            bool ok = (dn==0?has(R,y,x): dn==2?has(L,y,x): dn==1?has(D,x,y):has(U,x,y));
            if(!ok) continue;
            const auto& v=colB[x]; int iy=lower_bound(v.begin(),v.end(),y)-v.begin(); int ub=v[iy-1];
            addIv(nD,x,ub+1,y);
        }

        normalize(nR); normalize(nL); normalize(nU); normalize(nD);
        R.swap(nR); L.swap(nL); U.swap(nU); D.swap(nD);
    }

    auto sum=[&](const IvMap& mp)->ll{ ll s=0; for(auto&kv:mp) for(auto& iv:kv.second) s += (ll)iv.second - iv.first + 1; return s; };
    cout << (sum(R)+sum(L)+sum(U)+sum(D)) << '\n';
    return 0;
}
accuracy: 1
time_ms: 730
memory_kb: 102172
final_rank: 4

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

using ll = long long;

// 区間集合：key（行or列）ごとに [l,r] の集合
using Interval = pair<int,int>;
using IntervalMap = unordered_map<int, vector<Interval>>;

// 区間追加（未併合）
inline void add_interval(IntervalMap &mp, int key, int l, int r){
    if(l>r) return;
    auto &v = mp[key];
    v.emplace_back(l,r);
}

// v は [l,r] の列。l 昇順にソート＆併合（隣接もマージ）
static void sort_and_merge(vector<Interval> &v){
    if(v.empty()) return;
    sort(v.begin(), v.end());
    vector<Interval> res;
    res.reserve(v.size());
    int cl=v[0].first, cr=v[0].second;
    for(size_t i=1;i<v.size();++i){
        int l=v[i].first, r=v[i].second;
        if(l<=cr+1){ cr=max(cr,r); }
        else{ res.emplace_back(cl,cr); cl=l; cr=r; }
    }
    res.emplace_back(cl,cr);
    v.swap(res);
}

// 全キーに対して併合
static void normalize(IntervalMap &mp){
    for(auto &kv: mp) sort_and_merge(kv.second);
}

// 点包含（key の区間群に pos が含まれるか）
inline bool contains(const IntervalMap &mp, int key, int pos){
    auto it = mp.find(key);
    if(it==mp.end()) return false;
    const auto &v = it->second;
    int L=0, R=(int)v.size()-1;
    while(L<=R){
        int M=(L+R)>>1;
        if(v[M].first<=pos && pos<=v[M].second) return true;
        if(pos < v[M].first) R=M-1; else L=M+1;
    }
    return false;
}

// 2D 座標をハッシュ
struct PairHash{
    size_t operator()(const pair<int,int>&p) const noexcept{
        return (static_cast<uint64_t>(p.first)<<32) ^ static_cast<uint32_t>(p.second);
    }
};

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

    int w,h,gx,gy,n;
    if(!(cin>>w>>h>>gx>>gy>>n)) return 0;
    vector<pair<int,int>> obs(n);
    for(int i=0;i<n;++i){ cin>>obs[i].first>>obs[i].second; }
    string Rcmd; cin>>Rcmd;
    int m = (int)Rcmd.size();

    // 障害物セット
    unordered_set<pair<int,int>,PairHash> blocked;
    blocked.reserve(n*2+ (w+h)*2);
    for(auto &p: obs) blocked.insert(p);

    // 行ごとの障害物 x（番兵 0, w+1 付き）
    vector<vector<int>> rowBlocks(h+1);
    for(int y=1;y<=h;++y){
        rowBlocks[y].push_back(0);
        rowBlocks[y].push_back(w+1);
    }
    for(auto &p: obs) rowBlocks[p.second].push_back(p.first);
    for(int y=1;y<=h;++y){
        auto &v=rowBlocks[y];
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    }
    // 列ごとの障害物 y（番兵 0, h+1 付き）
    vector<vector<int>> colBlocks(w+1);
    for(int x=1;x<=w;++x){
        colBlocks[x].push_back(0);
        colBlocks[x].push_back(h+1);
    }
    for(auto &p: obs) colBlocks[p.first].push_back(p.second);
    for(int x=1;x<=w;++x){
        auto &v=colBlocks[x];
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    }

    auto is_blocked = [&](int x,int y)->bool{
        return (x<1||x>w||y<1||y>h) || blocked.count({x,y});
    };

    // 境界マス（直進してすぐ止まる終点になり得る自由マス）を列挙
    vector<pair<int,int>> RB,LB,UB,DB; // 右/左/上/下 へ直進したときの終点候補
    RB.reserve(n + h + 10);
    LB.reserve(n + h + 10);
    UB.reserve(n + w + 10);
    DB.reserve(n + w + 10);

    // 壁由来
    for(int y=1;y<=h;++y){
        if(!is_blocked(w,y))   RB.emplace_back(w,y);
        if(!is_blocked(1,y))   LB.emplace_back(1,y);
    }
    for(int x=1;x<=w;++x){
        if(!is_blocked(x,1))   UB.emplace_back(x,1);
        if(!is_blocked(x,h))   DB.emplace_back(x,h);
    }
    // 障害物の隣
    for(auto &p: obs){
        int x=p.first, y=p.second;
        if(x-1>=1 && !is_blocked(x-1,y)) RB.emplace_back(x-1,y);
        if(x+1<=w && !is_blocked(x+1,y)) LB.emplace_back(x+1,y);
        if(y-1>=1 && !is_blocked(x,y-1)) DB.emplace_back(x,y-1);
        if(y+1<=h && !is_blocked(x,y+1)) UB.emplace_back(x,y+1);
    }

    // 命令の左/右回転
    auto leftTurn = [&](int d)->int{ // 0:R,1:D,2:L,3:U
        return (d+3)&3;
    };
    auto rightTurn = [&](int d)->int{
        return (d+1)&3;
    };

    // 「G をそのセグメント中で通過する」開始状態（Hit）を区間で追加
    auto add_hits = [&](IntervalMap &Rmap, IntervalMap &Lmap,
                        IntervalMap &Umap, IntervalMap &Dmap){
        // 行 gy
        {
            const auto &v = rowBlocks[gy];
            // v は 0 < ... < w+1、gx は障害物ではない
            int idx = int(lower_bound(v.begin(), v.end(), gx) - v.begin()); // 初の >=gx
            int rightB = v[idx];      // > gx
            int leftB  = v[idx-1];    // < gx
            // 右向き： [leftB+1 .. gx]
            add_interval(Rmap, gy, leftB+1, gx);
            // 左向き： [gx .. rightB-1]
            add_interval(Lmap, gy, gx, rightB-1);
        }
        // 列 gx
        {
            const auto &v = colBlocks[gx];
            int idy = int(lower_bound(v.begin(), v.end(), gy) - v.begin());
            int downB = v[idy];       // > gy
            int upB   = v[idy-1];     // < gy
            // 上向き(U)：y 減少、開始 y ∈ [gy .. downB-1]
            add_interval(Umap, gx, gy, downB-1);
            // 下向き(D)：y 増加、開始 y ∈ [upB+1 .. gy]
            add_interval(Dmap, gx, upB+1, gy);
        }
    };

    // C_{m+1} を Hit で初期化
    IntervalMap Rmap, Lmap, Umap, Dmap; // 開始状態集合（方向別）
    Rmap.reserve(1024); Lmap.reserve(1024); Umap.reserve(1024); Dmap.reserve(1024);
    add_hits(Rmap,Lmap,Umap,Dmap);
    normalize(Rmap); normalize(Lmap); normalize(Umap); normalize(Dmap);

    // 後ろへ畳み込み
    for(int step=m-1; step>=0; --step){
        char rc = Rcmd[step];
        IntervalMap nR, nL, nU, nD;
        nR.reserve(Rmap.size()+16);
        nL.reserve(Lmap.size()+16);
        nU.reserve(Umap.size()+16);
        nD.reserve(Dmap.size()+16);

        // まず Hit を加える（このセグメント中に G を踏む開始状態）
        add_hits(nR,nL,nU,nD);

        // 命令 rc を適用する逆像：次セグメントの開始状態（Rmap/Lmap/Umap/Dmap）から、
        // 一つ前のセグメントの終点（境界マス）を経由して、その直進の開始区間を復元
        // dir_j (今セグメントの直進向き) の境界マス p=(x,y) について、
        // dir_{j+1} = turn(rc, dir_j) が次セグメントの開始向き。
        auto process_RB = [&](){ // dir_j = R（行 y）、p in RB
            for(auto &p: RB){
                int x=p.first, y=p.second;
                int dir_next = (rc=='L') ? leftTurn(0) : rightTurn(0); // 0=R
                bool ok = false;
                if(dir_next==3) ok = contains(Umap, x, y);      // U
                else if(dir_next==1) ok = contains(Dmap, x, y); // D
                else if(dir_next==0) ok = contains(Rmap, y, x); // R（あり得ないが一応）
                else if(dir_next==2) ok = contains(Lmap, y, x); // L
                if(!ok) continue;
                // 左側の直前ブロッカー
                const auto &vb = rowBlocks[y];
                int idx = int(lower_bound(vb.begin(), vb.end(), x) - vb.begin());
                int leftB = vb[idx-1];
                add_interval(nR, y, leftB+1, x);
            }
        };
        auto process_LB = [&](){ // dir_j = L
            for(auto &p: LB){
                int x=p.first, y=p.second;
                int dir_next = (rc=='L') ? leftTurn(2) : rightTurn(2); // 2=L
                bool ok = false;
                if(dir_next==3) ok = contains(Umap, x, y);
                else if(dir_next==1) ok = contains(Dmap, x, y);
                else if(dir_next==0) ok = contains(Rmap, y, x);
                else if(dir_next==2) ok = contains(Lmap, y, x);
                if(!ok) continue;
                // 右側の次ブロッカー
                const auto &vb = rowBlocks[y];
                int idx = int(upper_bound(vb.begin(), vb.end(), x) - vb.begin());
                int rightB = vb[idx];
                add_interval(nL, y, x, rightB-1);
            }
        };
        auto process_UB = [&](){ // dir_j = U（列 x）
            for(auto &p: UB){
                int x=p.first, y=p.second;
                int dir_next = (rc=='L') ? leftTurn(3) : rightTurn(3); // 3=U
                bool ok = false;
                if(dir_next==0) ok = contains(Rmap, y, x);
                else if(dir_next==2) ok = contains(Lmap, y, x);
                else if(dir_next==1) ok = contains(Dmap, x, y);
                else if(dir_next==3) ok = contains(Umap, x, y);
                if(!ok) continue;
                // 下側の次ブロッカー（y 増加方向）
                const auto &vb = colBlocks[x];
                int idy = int(upper_bound(vb.begin(), vb.end(), y) - vb.begin());
                int downB = vb[idy];
                add_interval(nU, x, y, downB-1);
            }
        };
        auto process_DB = [&](){ // dir_j = D
            for(auto &p: DB){
                int x=p.first, y=p.second;
                int dir_next = (rc=='L') ? leftTurn(1) : rightTurn(1); // 1=D
                bool ok = false;
                if(dir_next==0) ok = contains(Rmap, y, x);
                else if(dir_next==2) ok = contains(Lmap, y, x);
                else if(dir_next==1) ok = contains(Dmap, x, y);
                else if(dir_next==3) ok = contains(Umap, x, y);
                if(!ok) continue;
                // 上側の直前ブロッカー（y 減少方向）
                const auto &vb = colBlocks[x];
                int idy = int(lower_bound(vb.begin(), vb.end(), y) - vb.begin());
                int upB = vb[idy-1];
                add_interval(nD, x, upB+1, y);
            }
        };

        process_RB();
        process_LB();
        process_UB();
        process_DB();

        normalize(nR); normalize(nL); normalize(nU); normalize(nD);
        Rmap.swap(nR); Lmap.swap(nL); Umap.swap(nU); Dmap.swap(nD);
    }

    // 答え：C_1 の状態数（区間長の総和）
    auto sum_len = [](const IntervalMap &mp)->long long{
        long long s=0;
        for(auto &kv: mp){
            for(auto &iv: kv.second){
                s += (long long)iv.second - (long long)iv.first + 1;
            }
        }
        return s;
    };
    long long ans = sum_len(Rmap) + sum_len(Lmap) + sum_len(Umap) + sum_len(Dmap);
    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 710
memory_kb: 102596
final_rank: 3

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

typedef long long lli;

typedef pair<lli, lli> P;

const lli MAX = 100000;

lli w, h, gx, gy, n;
vector<P> input;
vector<lli> vec[4][MAX+1]; //(x, y)
string r;

bool check(lli x, lli y, lli d){
  bool f = false;
  for(lli i=0;i<=r.size();i++){
    lli nx, ny;
    if(d == 0){
      nx = x;
      ny = *(lower_bound(vec[0][x].begin(), vec[0][x].end(), -y));
      ny = -ny;
      if(nx == gx && ny == gy) return true;
      ny = ny + 1;
      if(nx == gx && ny <= gy && gy <= y) return true;

    }
    if(d == 1){
      nx = *(lower_bound(vec[1][y].begin(), vec[1][y].end(), x));
      ny = y;
      if(nx == gx && ny == gy) return true;
      nx = nx - 1;
      if(x <= gx && gx <= nx && ny == gy) return true;
    }
    if(d == 2){
      nx = x;
      ny = *(lower_bound(vec[2][x].begin(), vec[2][x].end(), y));
      if(nx == gx && ny == gy) return true;
      ny = ny - 1;
      if(nx == gx && y <= gy && gy <= ny) return true;
    }
    if(d == 3){
      nx = *(lower_bound(vec[3][y].begin(), vec[3][y].end(), -x));
      ny = y;
      nx = -nx;
      if(nx == gx && ny == gy) return true;
      nx = nx + 1;
      if(nx <= gx && gx <= x && ny == gy) return true;
    }
    x = nx;
    y = ny;
    if(i == r.size()) break;
    if(r[i] == 'R') d = (d + 1) % 4;
    else d = (d - 1 + 4) % 4;
  }
  return false;
}

lli solve(){
  lli res = 0;
  for(lli i=0;i<=MAX;i++){
    for(int j=0;j<4;j++) vec[j][i].clear();
  }
  for(lli i=0;i<input.size();i++){
    vec[1][input[i].second].push_back(input[i].first);
    vec[3][input[i].second].push_back(input[i].first);
  }
  vec[1][gy].push_back(gx);
  vec[3][gy].push_back(gx);
  for(lli i=0;i<input.size();i++){
    vec[0][input[i].first].push_back(input[i].second);
    vec[2][input[i].first].push_back(input[i].second);
  }
  vec[0][gx].push_back(gy);
  vec[2][gx].push_back(gy);
  for(lli i=0;i<4;i++){
    for(lli j=1;j<=MAX;j++){
      vec[i][j].push_back(0);
      vec[i][j].push_back((i%2==0?h:w)+1);
    }
  }
  for(lli i=0;i<=MAX;i++){
    for(lli j=0;j<vec[0][i].size();j++){
      vec[0][i][j] = -vec[0][i][j];
    }
    for(lli j=0;j<vec[3][i].size();j++){
      vec[3][i][j] = -vec[3][i][j];
    }
  }
  for(lli i=0;i<=MAX;i++){
    for(lli j=0;j<4;j++){
      if(vec[j][i].size() > 0) sort(vec[j][i].begin(), vec[j][i].end());
    }
  }
  for(lli d=0;d<4;d++){
    lli upper = (d%2==0?w:h);
    for(lli i=1;i<=upper;i++){
      for(lli j=1;j<vec[d][i].size();j++){
        if(d % 2 == 1){
          lli sx = vec[d][i][j]-1;
          if(d == 3) sx = -sx;
          if(sx <= 0 || sx > w) continue;
          if(vec[d][i][j] - vec[d][i][j-1] - 1 > 0 && check(sx, i, d)){
            res += vec[d][i][j] - vec[d][i][j-1] - 1;
          }
        }
        if(d % 2 == 0){
          lli sy = vec[d][i][j]-1;
          if(d == 0) sy = -sy;
          if(sy <= 0 || sy > h) continue;
          if(vec[d][i][j] - vec[d][i][j-1] - 1 > 0 && check(i, sy, d)){
            res += vec[d][i][j] - vec[d][i][j-1] - 1;
          }
        }
      }
    }
  }
  return res;
}

main(){
  cin >> w >> h >> gx >> gy >> n;
  for(lli i=0;i<n;i++){
    lli x, y;
    cin >> x >> y;
    input.push_back(P(x, y));
  }
  cin >> r;
  cout << solve() + 4 << endl;
}
accuracy: 1
time_ms: 340
memory_kb: 30148
final_rank: 2