Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

縄張り(Territory)

あなたは南北方向にとても長く伸びたたくさんの道路と，東西方向にとても長く伸びたたくさんの道路が交わった形をした街に住んでいる．隣り合う2 つの南北方向の道路の間隔は 1 km である．また，隣り合う 2 つの東西方向の道路の間隔も 1 km である．

この街には市役所が 1 つある．市役所のある交差点を $(0,0)$ と表す．この街の交差点は 2 つの整数 $i, j$ を用いて交差点 $(i, j)$ と表される．すなわち，交差点 $(i, j)$ とは，交差点 $(0,0)$ から東に $i$ km ($i < 0$ のときは西に $-i$ km)，北に $j$ km ( $j < 0$ のときは南に $-j$ km) 進んだ位置の交差点を表す．

市役所ではジョイ君という名の 1 匹の犬を飼っている．ジョイ君は $K$ 日間の散歩の計画を立てた．散歩の計画は以下の通りである．

$K$ 日のうち最初の日の朝にはジョイ君は交差点 $(0,0)$ にいる．ジョイ君は交差点 $(0,0)$ に印を付ける．$(0,0)$ 以外にはジョイ君が印を付けた交差点はない．

$K$ 日のそれぞれの日の昼に散歩を行う．1 日の散歩は $N$ 回のステップからなる．各ステップでは交差点から隣の交差点へと移動し，移動先に印を付ける．ジョイ君がそれぞれの日の昼にどう移動するかは日によらず一定である．

昼の移動が終わった後は，現在いる交差点で次の日の朝まで寝る．

市役所では $K$ 日間の散歩によってできるジョイ君の縄張りについて話題になっている．4 つの交差点 $(a,b),(a + 1,b),(a + 1,b + 1),(a,b + 1)$ のいずれにもジョイ君が 1 回以上印を付けているとき，4 つの交差点で囲まれた区画はジョイ君の縄張りに属する．

あなたは，ジョイ君の散歩計画から，ジョイ君の縄張りに属する区画の個数を計算するプログラムを作成することとなった．

この街の道路はとても長く，また，南北方向にも東西方向にも十分たくさんの道路があるため，散歩の途中でジョイ君が道路の端や街の端に到達することはない．

課題

ジョイ君の散歩計画が与えられると，ジョイ君の縄張りに属する区画の個数を求めるプログラムを作成せよ．

入力

標準入力から以下の入力を読み込め．

1 行目には 2 個の整数 $N, K$ が空白を区切りとして書かれている．これはそれぞれの日の散歩が $N$ 回のステップからなり，散歩計画が $K$ 日間に渡ることを表している．

2 行目には長さ $N$ の文字列 $S$ が書かれている．文字列 $S$ のうち左から $p$ 文字目 $(1 \leq p \leq N)$ の文字 $C_p$ は E，N，W，S のいずれかである．これらの文字は以下のことを表す．

     文字 $C_p$ が E であるならば，$p$ 番目のステップで東隣の交差点に移動することを表す．

     文字 $C_p$ が N であるならば，$p$ 番目のステップで北隣の交差点に移動することを表す．

     文字 $C_p$ が W であるならば，$p$ 番目のステップで西隣の交差点に移動することを表す．

     文字 $C_p$ が S であるならば，$p$ 番目のステップで南隣の交差点に移動することを表す．

ここで，交差点$(i, j)$ に対して東隣，北隣，西隣，南隣の交差点はそれぞれ，交差点 $(i + 1, j)$，交差点$(i, j + 1)$，交差点$(i - 1, j)$，交差点$(i, j - 1)$ である．

出力

標準出力に，ジョイ君の縄張りに属する区画の個数を 1 行で出力せよ．

制限

すべての入力データは以下の条件を満たす．

$1 \leq N \leq 100 000$

$1 \leq K \leq 1 000 000 000$

入出力例

入力例1

12 1
EENWSEEESWWS

出力例1

3

この入力例では，散歩は 1 日間で行われる．1 日目にジョイ君は市役所から出発して下図のように移動する．黒丸はジョイ君が印を付けた交差点，白丸はジョイ君が印を付けていない交差点，二重丸は市役所のある交差点，数字は各ステップを表す．

ジョイ君の移動経路

入力例 1 において，下図の斜線部分で示された 3 個の区画がジョイ君の縄張りに属する．

入力例1 におけるジョイ君の縄張り

入力例2

12 2
EENWSEEESWWS

出力例2

7

入力例 2 では，散歩が 2 日間に渡り行われる．それぞれの日の移動経路は入力例 1 と同一である．散歩が完了したとき，下図の斜線部分で示された 7 個の区画がジョイ君の縄張りに属する．

入力例2 におけるジョイ君の縄張り

入力例3

7 1
ENNWNNE

出力例3

0

入力例 3 では，ジョイ君の縄張りに属する区画は存在しない．

入力例4

16 5
WSESSSWWWEEENNNW

出力例4

21

第15回 日本情報オリンピック本選 課題   2016 年 2 月 14 日

Solution in C++ (judge verdict: Accepted)

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

typedef long long ll;
typedef pair < ll , ll > Pi;
typedef pair < Pi , Pi > PPi;
typedef pair < ll , Pi > Ti;
const ll LLINF = 1LL << 60;
const int INF = (1 << 30) - 1;

char ch[] = "NESW";
ll dy[] = {-1, 0, 1, 0};
ll dx[] = {0, 1, 0, -1};

ll llabs(ll n) { return (n < 0 ? -n : n); }

ll N, K;
string S;
Pi route[200005];
ll vecy = 0, vecx = 0;
vector < PPi > data;
ll ans = 0;
ll sum[4][200005];
int main()
{
    cin >> N >> K >> S;
    for(int i = 0; i < N; i++) {
        int j = 0;
        while(S[i] != ch[j]) j++;
        vecy += dy[j], vecx += dx[j];
        route[i + 1] = Pi(vecy, vecx);
    }
    route[0] = Pi(INF, 2 * N);
    for(int i = 1; i <= N; i++) {
        if(vecy < 0) route[i].first = -route[i].first;
        if(vecx < 0) route[i].second = -route[i].second;
        if(vecx == 0) swap(route[i].first, route[i].second);
        route[i].first += INF, route[i].second += N * 2;
    }
    vecy = llabs(vecy); vecx = llabs(vecx);
    if(vecx == 0) vecx = vecy, vecy = 0;
    sort(route, route + N + 1);
    if(vecx == 0) {
        for(int i = 0; i <= N;) {
            ll y = route[i].first, x = route[i].second;
            Pi *a = route, *b = route + N + 1;
            if(binary_search(a, b, Pi(y + 1, x)) && binary_search(a, b, Pi(y, x + 1)) && binary_search(a, b, Pi(y + 1, x + 1))) ans++;
            while(i <= N && route[i].first == y && route[i].second == x) i++;
        }
        cout << ans << endl;
        return (0);
    }
    for(int i = 0; i <= N; i++) {
        ll y = route[i].first, x = route[i].second;
        data.push_back(PPi(Pi(y - x / vecx * vecy, x % vecx), Pi(x / vecx, x / vecx + K)));
    }
    sort(data.begin(), data.end());
    data.erase(unique(data.begin(), data.end()), data.end());
    for(int i = 0; i < data.size();) {
        vector < ll > comp;
        vector < Ti > d;
        map < ll, ll > conv;
        
        ll now[4] = {};

        ll r, u, ru;
        ll iy = data[i].first.first, ix = data[i].first.second;
        ll plus = (ix + 1) / vecx;
        Pi pp[4] = {data[i].first, Pi(iy - plus * vecy, (ix + 1) % vecx), Pi(iy + 1, ix), Pi(iy + 1 - plus * vecy, (ix + 1) % vecx)};
        Pi nop = Pi(-LLINF, -LLINF);
        ll pos[4];
        pos[0] = i;
        for(int j = 1; j < 4; j++) pos[j] = lower_bound(data.begin(), data.end(), PPi(pp[j], nop)) - data.begin();
        for(int j = 0; j < 4; j++) {
            while(pos[j] < data.size() && data[pos[j]].first == pp[j]) {
                ll s = data[pos[j]].second.first - plus * (j % 2) , t = data[pos[j]].second.second - plus * (j % 2);
                comp.push_back(s); comp.push_back(t);
                d.push_back(Ti(1, Pi(j, s)));
                d.push_back(Ti(-1, Pi(j, t)));
                pos[j]++;
            }
        }
        sort(comp.begin(), comp.end());
        comp.erase(unique(comp.begin(), comp.end()), comp.end());
        for(int j = 0; j < comp.size(); j++) conv[comp[j]] = j;
        for(int p = 0; p < 4; p++) for(int j = 0; j < comp.size(); j++) sum[p][j] = 0;
        for(int j = 0; j < d.size(); j++) sum[d[j].second.first][conv[d[j].second.second]] += d[j].first;
        for(int j = 0; j < comp.size() - 1; j++) {
            bool flag = true;
            for(int k = 0; k < 4; k++) {
                now[k] += sum[k][j];
                if(now[k] <= 0) flag = false;
            }
            if(flag) ans += comp[j + 1] - comp[j];
        }
        i = pos[0];
    }
    cout << ans << endl;
    return (0);
}