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

/**
 * Dont raise your voice, improve your argument.
 * --Desmond Tutu
 */

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

const bool ready = []() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout << fixed << setprecision(12);
  return true;
}();

const double PI = acos(-1);
using ll = long long;
#define int ll
#define all(v) (v).begin(), (v).end()
#define fori(n) for (int i = 0; i < int(n); i++)

#define cini(i)                                                                \\
  int i;                                                                       \\
  cin >> i;
#define cins(s)                                                                \\
  string s;                                                                    \\
  cin >> s;
#define cind(d)                                                                \\
  double d;                                                                    \\
  cin >> d;
#define cinai(a, n)                                                            \\
  vi a(n);                                                                     \\
  fori(n) { cin >> a[i]; }
#define cinas(s, n)                                                            \\
  vs s(n);                                                                     \\
  fori(n) { cin >> s[i]; }
#define cinad(a, n)                                                            \\
  vd a(n);                                                                     \\
  fori(n) { cin >> a[i]; }

using pii = pair<int, int>;
using pdd = pair<double, double>;
using vd = vector<double>;
using vb = vector<bool>;
using vi = vector<int>;
using vvi = vector<vi>;
using vs = vector<string>;

/* see
 *https://cp-algorithms.com/data_structures/sqrt_decomposition.html#toc-tgt-4
 * Queries are inclusive l and inclusive r.
 **/

// const int BLOCK_SIZE=(int)sqrt(5e5+5)+1;
const int BLOCK_SIZE = 512;

bool mo_cmp(int pfirst, int psecond, int qfirst, int qsecond) {
  if (pfirst / BLOCK_SIZE != qfirst / BLOCK_SIZE)
    return pfirst < qfirst || (pfirst == qfirst && psecond < qsecond);
  return ((pfirst / BLOCK_SIZE) & 1) ? (psecond < qsecond)
                                     : (psecond > qsecond);
}

struct Query {
  int l, r, idx;

  bool operator<(Query other) const { return mo_cmp(l, r, other.l, other.r); }
};

const int N = 5e5 + 5;
int gans = 0;
vi f(N);
vi a(N);

inline void moremove(int idx) {
  if (--f[a[idx]] == 0)
    gans--;
}

inline void moadd(int idx) {
  if (++f[a[idx]] == 1)
    gans++;
}

inline int moget_answer() { return gans; }

vector<int> mo(vector<Query> &queries) {
  vector<int> answers(queries.size());
  sort(queries.begin(), queries.end());
  int cur_l = 0;
  int cur_r = -1;

  /* invariant: data structure will always reflect the range [cur_l, cur_r] */
  for (Query &q : queries) {
    while (cur_l > q.l) {
      cur_l--;
      moadd(cur_l);
    }
    while (cur_r < q.r) {
      cur_r++;
      moadd(cur_r);
    }
    while (cur_l < q.l) {
      moremove(cur_l);
      cur_l++;
    }
    while (cur_r > q.r) {
      moremove(cur_r);
      cur_r--;
    }
    answers[q.idx] = moget_answer();
  }
  return answers;
}

/* example impl of the three functions
 * for finding number of numbers in
 * interval where freq==number */

void solve() {
  cini(n);
  cini(q);
  for (int i = 0; i < n; i++)
    cin >> a[i];

  vector<Query> que(q);
  for (int i = 0; i < q; i++) {
    cin >> que[i].l >> que[i].r;
    que[i].l--;
    que[i].r--;
    que[i].idx = i;
  }

  vi ans = mo(que);

  for (int i = 0; i < q; i++) {
    cout << ans[i] << "\\n";
  }
}

signed main() { solve(); }


Error: TLE

Fixed submission:

/**
 * Dont raise your voice, improve your argument.
 * --Desmond Tutu
 */

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

const bool ready = []() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout << fixed << setprecision(12);
  return true;
}();

const double PI = acos(-1);
using ll = long long;
#define int ll
#define all(v) (v).begin(), (v).end()
#define fori(n) for (int i = 0; i < int(n); i++)

#define cini(i)                                                                \\
  int i;                                                                       \\
  cin >> i;
#define cins(s)                                                                \\
  string s;                                                                    \\
  cin >> s;
#define cind(d)                                                                \\
  double d;                                                                    \\
  cin >> d;
#define cinai(a, n)                                                            \\
  vi a(n);                                                                     \\
  fori(n) { cin >> a[i]; }
#define cinas(s, n)                                                            \\
  vs s(n);                                                                     \\
  fori(n) { cin >> s[i]; }
#define cinad(a, n)                                                            \\
  vd a(n);                                                                     \\
  fori(n) { cin >> a[i]; }

using pii = pair<int, int>;
using pdd = pair<double, double>;
using vd = vector<double>;
using vb = vector<bool>;
using vi = vector<int>;
using vvi = vector<vi>;
using vs = vector<string>;

/* see
 *https://cp-algorithms.com/data_structures/sqrt_decomposition.html#toc-tgt-4
 * Queries are inclusive l and inclusive r.
 **/

// const int BLOCK_SIZE=(int)sqrt(5e5+5)+1;
const int BLOCK_SIZE = 256;

bool cmp(pair<int, int> p, pair<int, int> q) {
  if (p.first / BLOCK_SIZE != q.first / BLOCK_SIZE)
    return p < q;
  return (p.first / BLOCK_SIZE & 1) ? (p.second < q.second)
                                    : (p.second > q.second);
}

struct Query {
  int l, r, idx;

  bool operator<(Query other) const {
    return cmp(make_pair(l, r), make_pair(other.l, other.r));
  }
};

const int N = 5e5 + 5;
int gans = 0;
vi f(N);
vi a(N);

inline void moremove(int idx) {
  int v = --f[a[idx]];
  assert(v >= 0);
  if (v == 0)
    gans--;
}

inline void moadd(int idx) {
  int v = ++f[a[idx]];
  if (v == 1)
    gans++;
}

inline int moget_answer() { return gans; }

vector<int> mo(vector<Query> &queries) {
  vector<int> answers(queries.size());
  sort(queries.begin(), queries.end());
  int cur_l = 0;
  int cur_r = -1;

  /* invariant: data structure will always reflect the range [cur_l, cur_r] */
  for (Query &q : queries) {
    while (cur_l > q.l) {
      cur_l--;
      moadd(cur_l);
    }
    while (cur_r < q.r) {
      cur_r++;
      moadd(cur_r);
    }
    while (cur_l < q.l) {
      moremove(cur_l);
      cur_l++;
    }
    while (cur_r > q.r) {
      moremove(cur_r);
      cur_r--;
    }
    answers[q.idx] = moget_answer();
  }
  return answers;
}

/* example impl of the three functions
 * for finding number of numbers in
 * interval where freq==number */

void solve() {
  cini(n);
  cini(q);
  for (int i = 0; i < n; i++)
    cin >> a[i];

  vector<Query> que(q);
  for (int i = 0; i < q; i++) {
    cin >> que[i].l >> que[i].r;
    que[i].l--;
    que[i].r--;
    que[i].idx = i;
  }

  vi ans = mo(que);

  for (int i = 0; i < q; i++) {
    cout << ans[i] << "\\n";
  }
}

signed main() { solve(); }