Problem p02599 (C++) — buggy submission, verdict: Time Limit Exceeded

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define pll pair<ll, ll>
#define pq priority_queue
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define endl '\\n'
#define ios ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define lb(c, x) distance(c.begin(), lower_bound(all(c), x))
#define ub(c, x) distance(c.begin(), upper_bound(all(c), x))

using namespace std;

template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

const ll INF = 1e18;
const ll mod = 1e9 + 7;

struct node {
  vector<int> rank0;
  vector<int> rank1;
  node *l = nullptr;
  node *r = nullptr;
};

node *build(vector<int> a, int h) {
  if (h == -1)
    return nullptr;
  vector<int> b[2];
  for (int x : a) {
    b[(x >> h) & 1].push_back(x); // hビット目が0のものと1のもので振り分け
  }
  node *res = new node();
  res->l = build(b[0], h - 1);
  res->r = build(b[1], h - 1);
  const int n = a.size();
  res->rank0.resize(n + 1);
  res->rank1.resize(n + 1);
  for (int i = 0; i < n; i++) {
    res->rank0[i + 1] = res->rank0[i] + ((a[i] >> h & 1) == 0);
    res->rank1[i + 1] = res->rank1[i] + ((a[i] >> h & 1) == 1);
  }
  return res;
}

int countGE(node *x, int l, int r, int v, int h) {
  if (h == -1)
    return r - l;
  int res = 0;
  if (((v >> h) & 1) == 0) {
    res += x->rank1[r] - x->rank1[l];
    res += countGE(x->l, x->rank0[l], x->rank0[r], v, h - 1);
  } else {
    res += countGE(x->r, x->rank1[l], x->rank1[r], v, h - 1);
  }
  return res;
}

int main() {
  ios;
  // 元問題は、「区間[l,r)の中の数字の種類数はいくつか」という問題。
  // これは、各項aiについて、biを「aj=aiとなるようなi<jを満たす最小のj」と定義すれば、
  //[l,r)におけるr以上のbiの個数を求める問題に置き換えることができる。
  int n, q;
  cin >> n >> q;
  vector<int> c(n);
  rep(i, n) cin >> c[i];
  vector<int> next(n); // 補助データ
  map<int, int> mp;
  for (int i = n - 1; i >= 0; i--) {
    if (mp.count(c[i])) {
      next[i] = mp[c[i]];
    } else {
      next[i] = n;
    }
    mp[c[i]] = i;
  }
  node *t = build(next, 20);
  while (q--) {
    int l, r;
    cin >> l >> r;
    l--;
    cout << countGE(t, l, r, r, 20) << endl;
  }
}


Error: TLE

Fixed submission:

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define pll pair<ll, ll>
#define pq priority_queue
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define endl '\\n'
#define ios ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define lb(c, x) distance(c.begin(), lower_bound(all(c), x))
#define ub(c, x) distance(c.begin(), upper_bound(all(c), x))

using namespace std;

template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

const ll INF = 1e18;
const ll mod = 1e9 + 7;

struct node {
  vector<int> rank0;
  vector<int> rank1;
  node *l = nullptr;
  node *r = nullptr;
};

node *build(vector<int> a, int h) {
  if (h == -1)
    return nullptr;
  vector<int> b[2];
  for (int x : a) {
    b[(x >> h) & 1].push_back(x); // hビット目が0のものと1のもので振り分け
  }
  node *res = new node();
  res->l = build(b[0], h - 1);
  res->r = build(b[1], h - 1);
  const int n = a.size();
  res->rank0.resize(n + 1);
  res->rank1.resize(n + 1);
  for (int i = 0; i < n; i++) {
    res->rank0[i + 1] = res->rank0[i] + ((a[i] >> h & 1) == 0);
    res->rank1[i + 1] = res->rank1[i] + ((a[i] >> h & 1) == 1);
  }
  return res;
}

int countGE(node *x, int l, int r, int v, int h) {
  if (h == -1)
    return r - l;
  int res = 0;
  if (((v >> h) & 1) == 0) {
    res += x->rank1[r] - x->rank1[l];
    res += countGE(x->l, x->rank0[l], x->rank0[r], v, h - 1);
  } else {
    res += countGE(x->r, x->rank1[l], x->rank1[r], v, h - 1);
  }
  return res;
}

int main() {
  // 元問題は、「区間[l,r)の中の数字の種類数はいくつか」という問題。
  // これは、各項aiについて、biを「aj=aiとなるようなi<jを満たす最小のj」と定義すれば、
  //[l,r)におけるr以上のbiの個数を求める問題に置き換えることができる。
  int n, q;
  cin >> n >> q;
  vector<int> c(n);
  rep(i, n) cin >> c[i];
  vector<int> next(n); // 補助データ
  map<int, int> mp;
  for (int i = n - 1; i >= 0; i--) {
    if (mp.count(c[i])) {
      next[i] = mp[c[i]];
    } else {
      next[i] = n;
    }
    mp[c[i]] = i;
  }
  node *t = build(next, 20);
  while (q--) {
    int l, r;
    cin >> l >> r;
    l--;
    cout << countGE(t, l, r, r, 20) << endl;
  }
}