Problem p03081 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#define REP(i, n) for (ll i = 0; i < n; i++)
#define REPR(i, n) for (ll i = n; i >= 0; i--)
#define FOR(i, m, n) for (ll i = m; i < n; i++)
#define FORR(i, m, n) for (ll i = m; i >= n; i--)
#define REPO(i, n) for (ll i = 1; i <= n; i++)
#define ll long long
#define INF 1999999999
#define MINF -1999999999
#define INF64 (ll)1 << 60
#define ALL(n) n.begin(), n.end()
#define MOD 1000000007
#define P pair<ll, ll>

ll n, q, a1, a2, v;
string s;
vector<pair<ll, ll>> p;
bool ok[110000];

bool ss(ll a) {
  ll now = a;
  REP(i, q) {
    if (p[i].first == s[now] - 'A') {
      if (p[i].second == 0)
        now--;
      else
        now++;
      if (now == n or now < 0)
        return false;
    }
  }
  return true;
}

// index が条件を満たすかどうか
bool isOK(int index, int key) {
  if (key == 0) {
    if (ss(index))
      return true;
    else
      return false;
  } else {
    if (ss(index))
      return false;
    if (ok[index])
      return false;
    return true;
  }
}

// 汎用的な二分探索のテンプレ
int bs(int key) {
  int left = -1; // 「index = 0」が条件を満たすこともあるので、初期値は -1
  int right = (int)s.size(); // 「index =
                             // a.size()-1」が条件を満たさないこともあるので、初期値は
                             // a.size()

  /* どんな二分探索でもここの書き方を変えずにできる！ */
  while (right - left > 1) {
    int mid = left + (right - left) / 2;

    if (isOK(mid, key))
      right = mid;
    else
      left = mid;
  }

  /* left は条件を満たさない最大の値、right は条件を満たす最小の値になっている
   */
  return right;
}

int main() {
  cin >> n >> q;
  cin >> s;
  REP(i, q) {
    char a, b;
    cin >> a >> b;
    ll c = 0;
    if (b == 'R')
      c++;
    p.push_back(make_pair(a - 'A', c));
  }
  a1 = bs(0);
  REP(i, a1) ok[i] = true;
  a2 = bs(1);
  cout << a2 - a1 << endl;
}


Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#define REP(i, n) for (ll i = 0; i < n; i++)
#define REPR(i, n) for (ll i = n; i >= 0; i--)
#define FOR(i, m, n) for (ll i = m; i < n; i++)
#define FORR(i, m, n) for (ll i = m; i >= n; i--)
#define REPO(i, n) for (ll i = 1; i <= n; i++)
#define ll long long
#define INF 1999999999
#define MINF -1999999999
#define INF64 (ll)1 << 60
#define ALL(n) n.begin(), n.end()
#define MOD 1000000007
#define P pair<ll, ll>

ll n, q, a1, a2, v;
string s;
vector<pair<ll, ll>> p;
bool ok[210000];

bool ss(ll a) {
  ll now = a;
  REP(i, q) {
    if (p[i].first == s[now] - 'A') {
      if (p[i].second == 0)
        now--;
      else
        now++;
      if (now == n or now < 0)
        return false;
    }
  }
  return true;
}

// index が条件を満たすかどうか
bool isOK(int index, int key) {
  if (key == 0) {
    if (ss(index))
      return true;
    else
      return false;
  } else {
    if (ss(index))
      return false;
    if (ok[index])
      return false;
    return true;
  }
}

// 汎用的な二分探索のテンプレ
int bs(int key) {
  int left = -1; // 「index = 0」が条件を満たすこともあるので、初期値は -1
  int right = (int)s.size(); // 「index =
                             // a.size()-1」が条件を満たさないこともあるので、初期値は
                             // a.size()

  /* どんな二分探索でもここの書き方を変えずにできる！ */
  while (right - left > 1) {
    int mid = left + (right - left) / 2;

    if (isOK(mid, key))
      right = mid;
    else
      left = mid;
  }

  /* left は条件を満たさない最大の値、right は条件を満たす最小の値になっている
   */
  return right;
}

int main() {
  cin >> n >> q;
  cin >> s;
  REP(i, q) {
    char a, b;
    cin >> a >> b;
    ll c = 0;
    if (b == 'R')
      c++;
    p.push_back(make_pair(a - 'A', c));
  }
  a1 = bs(0);
  REP(i, a1) ok[i] = true;
  a2 = bs(1);
  cout << a2 - a1 << endl;
}