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

#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

#define FSCNd64 "%" SCNd64
#define FPRId64 "%" PRId64

using namespace std;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vpii = vector<pii>;

#define PI 3.1415926535897932384626433832795

template <typename X> bool max_u(X &m, X v) {
  if (m < v) {
    m = v;
    return true;
  }
  return false;
}

template <typename X> bool min_u(X &m, X v) {
  if (m > v) {
    m = v;
    return true;
  }
  return false;
}

struct cnt_t {
  map<int, int> c;
};

struct segtree_t {
  int n;
  int base;
  std::vector<int> t;
  segtree_t(int n) : n(n) {
    for (base = 1; base < n; base *= 2)
      ;

    t.resize(base * 2);
  }

  void set_i(int x) {
    if (x == 0)
      return;
    t[x] = t[x * 2] + t[x * 2 + 1];
    set_i(x / 2);
  }

  void set(int x, int v) {
    int y = base + x;
    t[y] = (v != 0);
    set_i(y / 2);
  }

  int get_i(int x) {
    if (x == 0)
      return 0;
    int add = 0;
    if (x & 1)
      add = t[x - 1];
    return add + get_i(x / 2);
  }

  int get(int x) {
    int y = base + x;
    return t[y] + get_i(y);
  }

  void dump(void) {
    for (auto &m : t)
      cout << m << " ";
    cout << "\\n";
  }
};

struct solve {
  int n;
  vi c;
  segtree_t t;
  map<pii, int> ans;
  solve(int n, vi &c, vi &l, vi &r) : n(n), c(c), t(n + 1) {
    vvi x(n + 1);
    for (int i = 1; i <= n; i++) {
      x[c[i]].push_back(i);
    }

    for (int i = 1; i <= n; i++) {
      if (x[i].empty())
        continue;
      t.set(x[i].back(), 1);
    }
    // t.dump();
    int q = l.size();
    vpii rl;
    for (int i = 0; i < q; i++) {
      rl.push_back(make_pair(r[i], l[i]));
    }
    sort(rl.rbegin(), rl.rend());

    int xr = n;
    for (int i = 0; i < q; i++) {
      for (; xr > rl[i].first; xr--) {
        auto &tv = x[c[xr]];
        t.set(tv.back(), 0);
        tv.pop_back();
        if (tv.empty())
          continue;
        t.set(tv.back(), 1);
      }
      ans[rl[i]] = t.get(rl[i].first) - t.get(rl[i].second - 1);
      // cout << "ans " << rl[i].first << " " << rl[i].second << " " <<
      // ans[rl[i]] << "\\n";
    }
  }
  ll operator()(int l, int r) {
    auto it = ans.find(make_pair(r, l));
    return it->second;
  }
};

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  for (;;) {
    int n, q;
    cin >> n >> q;
    if (cin.fail())
      break;
    vi c(n + 1);
    for (int i = 1; i <= n; i++)
      cin >> c[i];

    vi l(q), r(q);
    for (int i = 0; i < q; i++)
      cin >> l[i] >> r[i];

    solve solver(n, c, l, r);
    for (int i = 0; i < q; i++) {
      cout << solver(l[i], r[i]) << "\\n";
    }
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

#define FSCNd64 "%" SCNd64
#define FPRId64 "%" PRId64

using namespace std;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vpii = vector<pii>;

#define PI 3.1415926535897932384626433832795

template <typename X> bool max_u(X &m, X v) {
  if (m < v) {
    m = v;
    return true;
  }
  return false;
}

template <typename X> bool min_u(X &m, X v) {
  if (m > v) {
    m = v;
    return true;
  }
  return false;
}

struct cnt_t {
  map<int, int> c;
};

struct segtree_t {
  int n;
  int base;
  std::vector<cnt_t> t;
  segtree_t(int n) : n(n) {
    for (base = 1; base < n; base *= 2)
      ;

    t.resize(base * 2);
  }

  void calc_i(int x) {
    auto &tt = t[x].c;
    tt = t[x * 2].c;
    for (auto &m : t[x * 2 + 1].c)
      tt[m.first] += m.second;
  }

  void construct(void) {
    for (int i = base - 1; i > 0; i--) {
      calc_i(i);
    }
  }

  void set(int x, int c) {
    int y = base + x;
    t[y].c[c] = 1;
  }

  void get_i(vi &ret, int x) {
    if (x <= 0)
      return;
    if (x & 1) {
      for (auto &m : t[x - 1].c)
        ret[m.first] += m.second;
    }
    get_i(ret, x / 2);
  }

  void get(vi &v, int x) {
    int y = base + x;
    for (auto &m : t[y].c) {
      v[m.first] += m.second;
    }
    get_i(v, y);
  }

  void dump(void) {
    for (int i = 1; i < base + n; i++) {
      cout << "t[" << i << "]=";
      for (auto &m : t[i].c)
        cout << "(" << m.first << "," << m.second << ")";
      cout << "\\n";
    }
  }
};

struct solve {
  int n;
  vi c;
  segtree_t t;
  int dupn, kndn;
  solve(int n, vi &c) : n(n), c(c), t(n + 1) {
    vi x(n + 1);
    for (int i = 1; i <= n; i++) {
      x[c[i]]++;
    }

    map<int, int> m;
    for (int i = 1; i <= n; i++) {
      if (x[i] >= 2)
        m[i] = m.size();
    }
    dupn = m.size();
    for (int i = 1; i <= n; i++) {
      if (x[i] == 1)
        m[i] = m.size();
    }
    kndn = m.size();

    for (int i = 1; i <= n; i++) {
      c[i] = m[c[i]];
      if (c[i] < dupn)
        t.set(i, c[i]);
    }
    t.construct();
    //		t.dump();
  }
  ll operator()(int l, int r) {
    if (r - l < 100) {
      vector<bool> f(kndn, false);
      int ans = 0;
      for (int i = l; i <= r; i++) {
        if (f[c[i]] == false) {
          f[c[i]] = true;
          ans++;
        }
      }
      return ans;
    }
    vi rc(dupn), lc(dupn);
    t.get(rc, r);
    t.get(lc, l - 1);
    int ans = r - l + 1;
    for (int i = 0; i < dupn; i++) {
      ans -= max(rc[i] - lc[i] - 1, 0);
    }
    return ans;
  }
};

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  for (;;) {
    int n, q;
    cin >> n >> q;
    if (cin.fail())
      break;
    vi c(n + 1);
    for (int i = 1; i <= n; i++)
      cin >> c[i];

    vi l(q), r(q);
    for (int i = 0; i < q; i++)
      cin >> l[i] >> r[i];

    solve solver(n, c);
    for (int i = 0; i < q; i++) {
      cout << solver(l[i], r[i]) << "\\n";
    }
  }
  return 0;
}