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

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>    // assert
#include <cmath>      // abs など
#include <functional> // greater など
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric> // accumulate, gcd など
#include <queue>
#include <set>
#include <stack>
#include <stdexcept>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
using namespace std;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for (int i = (a); i < (int)(b); i++)
typedef long long ll;

//////////////// //////////////// //////////////// ////////////////
///////////////////
//////////////// //////////////// //////////////// ////////////////
///////////////////

// [1,n]に格納
vector<int> fenwick;

// [1,c]の和
int fw_sum(int i) {
  int ret = 0;
  while (i >= 1) {
    ret += fenwick[i];
    i -= i & -i;
  }
  return ret;
}

// c番目にxを足す
void fw_add(int i, int x) {
  while (i <= fenwick.size()) {
    fenwick[i] += x;
    i += i & -i;
  }
}

struct interval {
  int right;
  int left;
  int index;
};

int main() {
  // 高速な入出力
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << setprecision(15); // 浮動小数の表示の精度

  int n, q;
  cin >> n >> q;
  fenwick.resize(n + 1);
  vector<int> col_s(n + 1);
  FOR(pos, 1, n + 1) {
    cin >> col_s[pos];
    col_s[pos]--;
  }
  vector<interval> intervals(q);
  rep(i_q, q) {
    int l, r;
    cin >> l >> r;
    intervals[i_q] = {r, l, i_q};
  }
  sort(intervals.begin(), intervals.end(),
       [](interval x, interval y) { return x.right < y.right; });

  // good_ball[color] : 一番右のcolor(0-indexed)の場所pos(1-indexed)
  vector<int> good_ball(n);
  vector<int> ans(q);
  int i_q_sorted = 0;
  FOR(pos, 1, n + 1) {
    // good_ball の更新
    if (good_ball[col_s[pos]] >= 1) {
      fw_add(good_ball[col_s[pos]], -1);
    }
    good_ball[col_s[pos]] = pos;
    fw_add(pos, 1);

    // ansに格納
    while (i_q_sorted < q and intervals[i_q_sorted].right == pos) {
      auto cur_int = intervals[i_q_sorted];
      ans[cur_int.index] = fw_sum(cur_int.right) - fw_sum(cur_int.left - 1);
#ifdef DEBUG
      clog << i_q_sorted << ' ' << cur_int.left << ' ' << cur_int.right << ' '
           << cur_int.index << ' ' << ans[cur_int.index] << '\\n';
#endif
      i_q_sorted++;
    }
  }

  rep(i_q, q) { cout << ans[i_q] << '\\n'; }

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>    // assert
#include <cmath>      // abs など
#include <functional> // greater など
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric> // accumulate, gcd など
#include <queue>
#include <set>
#include <stack>
#include <stdexcept>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
using namespace std;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for (int i = (a); i < (int)(b); i++)
typedef long long ll;

// #define DEBUG 1

//////////////// //////////////// //////////////// ////////////////
///////////////////
//////////////// //////////////// //////////////// ////////////////
///////////////////

// constexpr inline ll mod = 1'000'000'007;
constexpr int max_e = 19, max_n = 1 << max_e;

void magi(set<int> &s, set<int> t) {
  for (auto x : t) {
    s.insert(x);
  }
}

int main() {
  // 高速な入出力
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << setprecision(15); // 浮動小数の表示の精度

  int n, q;
  cin >> n >> q;
  vector<int> c_s(n);
  rep(i, n) {
    cin >> c_s[i];
    c_s[i]--;
  }

  // [max_n, 2*max_n)が葉, 1が根
  vector<set<int>> seg(2 * max_n);

  // init
  rep(i, n) { seg[max_n + i].insert(c_s[i]); }
  for (int e = max_e - 1; e >= 0; e--) {
    rep(i, 1 << e) {
      seg[(1 << e) + i] = seg[(1 << (e + 1)) + 2 * i];
      magi(seg[(1 << e) + i], seg[(1 << (e + 1)) + 2 * i + 1]);
    }
#ifdef DEBUG
    clog << e << '\\n';
    auto s = seg[(1 << e)];
    for (auto i : s) {
      clog << i << ' ';
    }
    clog << '\\n';
#endif
  }

  // [a,b) を求める
  auto calc = [&seg](auto self, int a, int b, int k, int l, int r) -> set<int> {
#ifdef DEBUG
    clog << "calc " << k << ' ' << l << ' ' << r << '\\n';
#endif
    if (r <= a or b <= l) {
#ifdef DEBUG
      clog << "triv\\n";
#endif
      return set<int>();
    }

    if (a <= l and r <= b) {
#ifdef DEBUG
      clog << "return seg " << seg[k].size() << '\\n';
#endif
      return seg[k];
    }
    auto vl = self(self, a, b, 2 * k, l, (l + r) / 2);
    auto vr = self(self, a, b, 2 * k + 1, (l + r) / 2, r);
    if (vl.size() < vr.size()) {
      swap(vl, vr);
    }
    magi(vl, vr);
#ifdef DEBUG
    clog << "merge " << vl.size() << '\\n';
#endif
    return vl;
  };

  rep(i, q) {
    int l, r;
    cin >> l >> r;
    l -= 1;
    auto s = calc(calc, l, r, 1, 0, max_n);
#ifdef DEBUG
    for (auto i : s) {
      clog << i << ' ';
    }
    clog << '\\n';
#endif
    cout << s.size() << endl;
  }

  return 0;
}