Problem p02589 (C++) — buggy submission, verdict: Runtime Error

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

using ll = long long;
typedef pair<int, int> P;
typedef pair<P, P> PP;
const ll MODA = 1e9 + 7, MODB = 17, MODC = 998244353, MODD = 123456789;
vector<PP> hsh[223456];
vector<int> v[26];

typedef int U;
struct SegmentTree {
  typedef vector<U> T;
  int n;
  U MIN = -1000000000, MAX = 1000000000, eps = 1;
  using F = function<T(T, T)>;
  ;

  F f = [](T a, T b) {
    T res;
    int nowa = 0, nowb = 0;
    while (nowa < a.size() || nowb < b.size()) {
      if (nowa == a.size())
        res.push_back(b[nowb++]);
      else if (nowb == b.size())
        res.push_back(a[nowa++]);
      else {
        if (a[nowa] < b[nowb])
          res.push_back(a[nowa++]);
        else
          res.push_back(b[nowb++]);
      }
    }
    return res;
  };

  T ti = vector<U>();
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(int n_) {
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
  }
  SegmentTree(const vector<U> &v) {
    int n_ = v.size();
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
    for (int i = 0; i < n_; i++)
      dat[n + i] = T(1, v[i]);
    for (int i = n - 1; i; i--)
      dat[i] = f(dat[(i << 1) | 0], dat[(i << 1), 1]);
  }

  void build(vector<int> &v) {
    int n_ = v.size();
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
    for (int i = 0; i < n_; i++)
      dat[n + i] = T(1, v[i]);
    for (int i = n - 1; i; i--)
      dat[i] = f(dat[(i << 1) | 0], dat[(i << 1) | 1]);
  }

  void init(int n_) {
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
  }

  int get(int x) { return dat[x + n][0]; }

  void set_val(int k, U x) {
    dat[k += n] = T(1, x);
    while (k >>= 1)
      dat[k] = f(dat[(k << 1) | 0], dat[(k << 1) | 1]);
  }

  T query(int a, int b) { //[a,b)の範囲でのソート結果を返す
    T vl = ti, vr = ti;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        vl = f(vl, dat[l++]); // 左端を使いたくなるのはブロックが奇数の時
      if (r & 1)
        vr = f(dat[--r], vr); // 右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return f(vl, vr);
  }

  inline void CHMIN(U &a, T v) {
    if (v.size() && a > v[0])
      a = v[0];
  }
  inline void CHMAX(U &a, T v) {
    if (v.size() && a < v[0])
      a = v[0];
  }

  U mx(int a, int b) { //[a,b)のmaxを返す
    U vl = MIN, vr = MIN;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        CHMAX(vl, dat[l++]); // 左端を使いたくなるのはブロックが奇数の時
      if (r & 1)
        CHMAX(vr, dat[--r]); // 右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return max(vl, vr);
  }
  U mi(int a, int b) { //[a,b)のminを返す
    U vl = MAX, vr = MAX;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        CHMIN(vl, dat[l++]); // 左端を使いたくなるのはブロックが奇数の時
      if (r & 1)
        CHMIN(vr, dat[--r]); // 右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return min(vl, vr);
  }

  int IKA(T v, U x) {
    int s = v.size();
    if (!s)
      return 0;
    if (v[0] > x)
      return 0;
    int l = -1, r = s;
    while (r - l > 1) {
      int m = (r + l) >> 1;
      if (v[m] > x)
        r = m;
      else
        l = m;
    }
    return r;
  }

  int howmany(int a, int b, U x) {
    T v = query(a, b);
    return IKA(v, x) - IKA(v, x - eps);
  }

  int G(vector<int> &d, int x) {
    int l = -1, r = d.size();
    while (r - l > 1) {
      int mid = (r + l) >> 1;
      (d[mid] >= x ? r : l) = mid;
    }
    return d.size() - r;
  }

  int Q(int a, int b, int x) { //[l,r)のx以上の個数
    int res = 0;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        res += G(dat[l++], x); // 左端を使いたくなるのはブロックが奇数の時
      if (r & 1)
        res += G(dat[--r], x); // 右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return res;
  }
};
SegmentTree seg[26]; // seg[i]のdat[j+n_]にはi+'a'がs[j]で最後に出た場所

signed main() {
  int n;
  cin >> n;
  vector<string> s(n);
  for (int i = 0; i < n; i++)
    cin >> s[i];
  for (int i = 0; i < n; i++)
    reverse(s[i].begin(), s[i].end());
  sort(s.begin(), s.end());
  for (int i = 0; i < n; i++) {
    vector<int> memo(26, -1);
    for (int j = 0; j < s[i].size(); j++)
      memo[s[i][j] - 'a'] = j;
    for (int j = 0; j < 26; j++)
      v[j].push_back(memo[j]);
  }
  for (int i = 0; i < 26; i++)
    seg[i].build(v[i]);
  for (int i = 0; i < n; i++) {
    ll a = 1, b = 1, c = 1, d = 1;
    hsh[i].push_back(PP(P(a, b), P(c, d)));
    for (int j = 0; j < s[i].size(); j++) {
      (a *= s[i][j] * (j + 1)) %= MODA;
      (b *= s[i][j] + j + 124) %= MODB;
      (c *= (s[i][j] * (j + 7))) %= MODC;
      (d += (s[i][j] * (j * j + 5) % MODD)) %= MODD;
      hsh[i].push_back(PP(P(++a, ++b), P(++c, ++d)));
    }
  }
  ll ans = 0;
  for (int i = 0; i < n; i++) {
    int st = -1, r = i + 1; //(st,i]がiと被る
    int L = s[i].size();
    while (r - st > 1) {
      int mid = (r + st) >> 1;
      (hsh[mid].size() >= L && hsh[mid][L - 1] == hsh[i][L - 1] ? r : st) = mid;
    }
    int l = i - 1, en = n; //[i,en)がiと被る
    while (en - l > 1) {
      int mid = (l + en) >> 1;
      (hsh[mid].size() >= L && hsh[mid][L - 1] == hsh[i][L - 1] ? l : en) = mid;
    }
    int la = s[i].back() - 'a';
    ans += (ll)seg[la].Q(st + 1, en, L - 1) - 1LL;
  }
  cout << ans << endl;
}


Error: -11

Fixed submission:

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

using ll = long long;
typedef pair<int, int> P;
typedef pair<P, P> PP;
const ll MODA = 1e9 + 7, MODB = 17, MODC = 998244353, MODD = 123456789;
vector<PP> hsh[223456];
vector<int> v[26];

typedef int U;
struct SegmentTree {
  typedef vector<U> T;
  int n;
  U MIN = -1000000000, MAX = 1000000000, eps = 1;
  using F = function<T(T, T)>;
  ;

  F f = [](T a, T b) {
    T res;
    int nowa = 0, nowb = 0;
    while (nowa < a.size() || nowb < b.size()) {
      if (nowa == a.size())
        res.push_back(b[nowb++]);
      else if (nowb == b.size())
        res.push_back(a[nowa++]);
      else {
        if (a[nowa] < b[nowb])
          res.push_back(a[nowa++]);
        else
          res.push_back(b[nowb++]);
      }
    }
    return res;
  };

  T ti = vector<U>();
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(int n_) {
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
  }
  SegmentTree(const vector<U> &v) {
    int n_ = v.size();
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
    for (int i = 0; i < n_; i++)
      dat[n + i] = T(1, v[i]);
    for (int i = n - 1; i; i--)
      dat[i] = f(dat[(i << 1) | 0], dat[(i << 1), 1]);
  }

  void build(vector<int> &v) {
    int n_ = v.size();
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
    for (int i = 0; i < n_; i++)
      dat[n + i] = T(1, v[i]);
    for (int i = n - 1; i; i--)
      dat[i] = f(dat[(i << 1) | 0], dat[(i << 1) | 1]);
  }

  void init(int n_) {
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
  }

  int get(int x) { return dat[x + n][0]; }

  void set_val(int k, U x) {
    dat[k += n] = T(1, x);
    while (k >>= 1)
      dat[k] = f(dat[(k << 1) | 0], dat[(k << 1) | 1]);
  }

  T query(int a, int b) { //[a,b)の範囲でのソート結果を返す
    T vl = ti, vr = ti;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        vl = f(vl, dat[l++]); // 左端を使いたくなるのはブロックが奇数の時
      if (r & 1)
        vr = f(dat[--r], vr); // 右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return f(vl, vr);
  }

  inline void CHMIN(U &a, T v) {
    if (v.size() && a > v[0])
      a = v[0];
  }
  inline void CHMAX(U &a, T v) {
    if (v.size() && a < v[0])
      a = v[0];
  }

  U mx(int a, int b) { //[a,b)のmaxを返す
    U vl = MIN, vr = MIN;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        CHMAX(vl, dat[l++]); // 左端を使いたくなるのはブロックが奇数の時
      if (r & 1)
        CHMAX(vr, dat[--r]); // 右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return max(vl, vr);
  }
  U mi(int a, int b) { //[a,b)のminを返す
    U vl = MAX, vr = MAX;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        CHMIN(vl, dat[l++]); // 左端を使いたくなるのはブロックが奇数の時
      if (r & 1)
        CHMIN(vr, dat[--r]); // 右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return min(vl, vr);
  }

  int IKA(T v, U x) {
    int s = v.size();
    if (!s)
      return 0;
    if (v[0] > x)
      return 0;
    int l = -1, r = s;
    while (r - l > 1) {
      int m = (r + l) >> 1;
      if (v[m] > x)
        r = m;
      else
        l = m;
    }
    return r;
  }

  int howmany(int a, int b, U x) {
    T v = query(a, b);
    return IKA(v, x) - IKA(v, x - eps);
  }

  int G(vector<int> &d, int x) {
    int l = -1, r = d.size();
    while (r - l > 1) {
      int mid = (r + l) >> 1;
      (d[mid] >= x ? r : l) = mid;
    }
    return d.size() - r;
  }

  int Q(int a, int b, int x) { //[l,r)のx以上の個数
    int res = 0;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        res += G(dat[l++], x); // 左端を使いたくなるのはブロックが奇数の時
      if (r & 1)
        res += G(dat[--r], x); // 右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return res;
  }
};
SegmentTree seg[26]; // seg[i]のdat[j+n_]にはi+'a'がs[j]で最後に出た場所

signed main() {
  int n;
  cin >> n;
  vector<string> s(n);
  for (int i = 0; i < n; i++)
    cin >> s[i];
  for (int i = 0; i < n; i++)
    reverse(s[i].begin(), s[i].end());
  sort(s.begin(), s.end());
  for (int i = 0; i < n; i++) {
    vector<int> memo(26, -1);
    for (int j = 0; j < s[i].size(); j++)
      memo[s[i][j] - 'a'] = j;
    for (int j = 0; j < 26; j++)
      v[j].push_back(memo[j]);
  }
  for (int i = 0; i < 26; i++)
    seg[i].build(v[i]);
  for (int i = 0; i < n; i++) {
    ll a = 1, b = 1, c = 1, d = 1;
    hsh[i].push_back(PP(P(a, b), P(c, d)));
    for (int j = 0; j < s[i].size(); j++) {
      (a *= s[i][j] * (j + 1)) %= MODA;
      (b *= s[i][j] + j + 124) %= MODB;
      (c *= (s[i][j] * (j + 7))) %= MODC;
      (d += (s[i][j] * (j * j + 5) % MODD)) %= MODD;
      hsh[i].push_back(PP(P(a, b), P(c, d)));
    }
  }
  ll ans = 0;
  for (int i = 0; i < n; i++) {
    int st = -1, r = i + 1; //(st,i]がiと被る
    int L = s[i].size();
    while (r - st > 1) {
      int mid = (r + st) >> 1;
      (s[mid].size() > L && hsh[mid][L - 1] == hsh[i][L - 1] ? r : st) = mid;
    }
    int l = i - 1, en = n + 1; //[i,en)がiと被る
    while (en - l > 1) {
      int mid = (l + en) >> 1;
      (s[mid].size() > L && hsh[mid][L - 1] == hsh[i][L - 1] ? l : en) = mid;
    }
    int la = s[i].back() - 'a';
    ans += (ll)seg[la].Q(st + 1, en, L - 1) - 1LL;
  }
  cout << ans << endl;
}