Problem p03322 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#define INF 1061109567
#define int long long
#define pb push_back
#define in(s) freopen(s, "r", stdin);
#define out(s) freopen(s, "w", stdout);
#define fi first
#define se second
#define bw(i, r, l) for (int i = r - 1; i >= l; i--)
#define fw(i, l, r) for (int i = l; i < r; i++)
#define fa(i, x) for (auto i : x)
using namespace std;
const int N = 5e5 + 10;
const int mod1 = 1e9 + 7, mod2 = 1e9 + 9, base = 121448;
typedef pair<int, int> ii;
int n, h[N][2], pw[N][2];
string s;
map<ii, int> mp;
void add(int &x, int y, int mod) {
  x += y;
  if (x >= mod)
    x -= mod;
}
void rem(int &x, int y, int mod) {
  x -= y;
  if (x < 0)
    x += mod;
}
int fpow(int a, int p, int mod) {
  if (!p)
    return 1;
  int ans = fpow(a, p >> 1, mod);
  ans = ans * ans % mod;
  if (p & 1)
    ans = ans * a % mod;
  return ans;
}
int inv(int x, int mod) { return fpow(x, mod - 2, mod); }
signed main() {
#ifdef aome
  in("aome.inp");
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> s;
  // Hash 'em. Then for a range L -> R, if the pointer at L is P, it's (h[r] -
  // h[l - 1]) / b ^ p
  pw[0][0] = pw[0][1] = 1;
  fw(i, 1, N) {
    pw[i][0] = pw[i - 1][0] * base % mod1;
    pw[i][1] = pw[i - 1][1] * base % mod2;
  }
  int cur = 25e4 + 5;
  fw(i, 0, n) {
    h[i][0] = i ? h[i - 1][0] : 0;
    h[i][1] = i ? h[i - 1][1] : 0;
    if (s[i] == '>')
      cur++;
    else if (s[i] == '<')
      cur--;
    else if (s[i] == '+')
      add(h[i][0], pw[cur][0], mod1), add(h[i][1], pw[cur][1], mod2);
    else
      rem(h[i][0], pw[cur][0], mod1), rem(h[i][1], pw[cur][1], mod2);
    // cout << "h["<<i<<"][0] = " << h[i][0] << ", 1 = " << h[i][1] << " cur = "
    // << cur << "\n";
    mp[ii(h[i][0], h[i][1])]++;
  }
  cur = 0;
  int ans = 0;
  ans += mp[ii(h[n - 1][0], h[n - 1][1])]; // 0 -> any good points
  fw(i, 0, n) {
    if (s[i] == '>')
      cur++;
    else if (s[i] == '<')
      cur--;
    mp[ii(h[i][0], h[i][1])]--;
    int pw0, pw1;
    if (cur >= 0)
      pw0 = pw[cur][0], pw1 = pw[cur][1];
    else
      pw0 = inv(pw[cur][0], mod1), pw1 = inv(pw[cur][1], mod2);
    // cout << (h[n - 1][0] * pw0 + h[i][0]) % mod1 << " " << (h[n - 1][1] * pw1
    // + h[i][1]) % mod2 << "\n";
    ans += mp[ii((h[n - 1][0] * pw0 + h[i][0]) % mod1,
                 (h[n - 1][1] * pw1 + h[i][1]) % mod2)];
  }
  cout << ans;
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
#define INF 1061109567
#define int long long
#define pb push_back
#define in(s) freopen(s, "r", stdin);
#define out(s) freopen(s, "w", stdout);
#define fi first
#define se second
#define bw(i, r, l) for (int i = r - 1; i >= l; i--)
#define fw(i, l, r) for (int i = l; i < r; i++)
#define fa(i, x) for (auto i : x)
using namespace std;
const int N = 5e5 + 10;
const int mod1 = 1e9 + 7, mod2 = 1e9 + 9, base = 121448;
typedef pair<int, int> ii;
int n, h[N][2], pw[N][2];
string s;
map<ii, int> mp;
void add(int &x, int y, int mod) {
  x += y;
  if (x >= mod)
    x -= mod;
}
void rem(int &x, int y, int mod) {
  x -= y;
  if (x < 0)
    x += mod;
}
int fpow(int a, int p, int mod) {
  if (!p)
    return 1;
  int ans = fpow(a, p >> 1, mod);
  ans = ans * ans % mod;
  if (p & 1)
    ans = ans * a % mod;
  return ans;
}
int inv(int x, int mod) { return fpow(x, mod - 2, mod); }
signed main() {
#ifdef aome
  in("aome.inp");
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> s;
  // Hash 'em. Then for a range L -> R, if the pointer at L is P, it's (h[r] -
  // h[l - 1]) / b ^ p
  pw[0][0] = pw[0][1] = 1;
  fw(i, 1, N) {
    pw[i][0] = pw[i - 1][0] * base % mod1;
    pw[i][1] = pw[i - 1][1] * base % mod2;
  }
  int cur = 25e4 + 5;
  fw(i, 0, n) {
    h[i][0] = i ? h[i - 1][0] : 0;
    h[i][1] = i ? h[i - 1][1] : 0;
    if (s[i] == '>')
      cur++;
    else if (s[i] == '<')
      cur--;
    else if (s[i] == '+')
      add(h[i][0], pw[cur][0], mod1), add(h[i][1], pw[cur][1], mod2);
    else
      rem(h[i][0], pw[cur][0], mod1), rem(h[i][1], pw[cur][1], mod2);
    // cout << "h["<<i<<"][0] = " << h[i][0] << ", 1 = " << h[i][1] << " cur = "
    // << cur << "\n";
    mp[ii(h[i][0], h[i][1])]++;
  }
  cur = 0;
  int ans = 0;
  ans += mp[ii(h[n - 1][0], h[n - 1][1])]; // 0 -> any good points
  fw(i, 0, n) {
    if (s[i] == '>')
      cur++;
    else if (s[i] == '<')
      cur--;
    mp[ii(h[i][0], h[i][1])]--;
    int pw0, pw1;
    if (cur >= 0)
      pw0 = pw[cur][0], pw1 = pw[cur][1];
    else
      pw0 = inv(pw[-cur][0], mod1), pw1 = inv(pw[-cur][1], mod2);
    // cout << (h[n - 1][0] * pw0 + h[i][0]) % mod1 << " " << (h[n - 1][1] * pw1
    // + h[i][1]) % mod2 << "\n";
    ans += mp[ii((h[n - 1][0] * pw0 + h[i][0]) % mod1,
                 (h[n - 1][1] * pw1 + h[i][1]) % mod2)];
  }
  cout << ans;
  return 0;
}