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

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
struct Node {
  Node *l, *r;
  int st, ed, sum;
} *root[501001], pool[26040404];
int tot, last[505050];
inline void Build(Node *&now, int st, int ed) {
  now = &pool[++tot];
  now->st = st;
  now->ed = ed;
  now->sum = 0;
  if (st == ed) {
    return;
  }
  int mid = ((st + ed) >> 1);
  Build(now->l, st, mid);
  Build(now->r, mid + 1, ed);
}
inline Node *Add(Node *now, int pos) {
  Node *ret = &pool[++tot];
  ret->st = now->st;
  ret->ed = now->ed;
  ret->sum = now->sum + 1;
  if (now->st == now->ed) {
    return ret;
  }
  if (now->l->ed >= pos) {
    ret->r = now->r;
    ret->l = Add(now->l, pos);
    return ret;
  } else {
    ret->l = now->l;
    ret->r = Add(now->r, pos);
    return ret;
  }
}
inline Node *minu(Node *now, int pos) {
  Node *ret = &pool[++tot];
  ret->st = now->st;
  ret->ed = now->ed;
  ret->sum = now->sum - 1;
  if (now->st == now->ed) {
    return ret;
  }
  if (now->l->ed >= pos) {
    ret->r = now->r;
    ret->l = minu(now->l, pos);
    return ret;
  } else {
    ret->l = now->l;
    ret->r = minu(now->r, pos);
    return ret;
  }
}
inline int getsum(Node *now, int st, int ed) {
  if (now->st > ed || now->ed < st)
    return 0;
  if (now->st >= st && now->ed <= ed) {
    return now->sum;
  }
  return getsum(now->l, st, ed) + getsum(now->r, st, ed);
}

template <class T> inline void read(T &x) {
  x = 0;
  char c = getchar();
  int f = 1;
  while (!isdigit(c)) {
    if (c == '-')
      f = -1;
    c = getchar();
  }
  while (isdigit(c)) {
    x = x * 10 + c - '0';
    c = getchar();
  }
  x *= f;
}

int main() {
  int n;
  int q, li, ri;
  read(n);
  read(q);
  Build(root[0], 1, n);
  int cc;
  for (int i = 1; i <= n; i++) {
    read(cc);
    root[i] = Add(root[i - 1], i);
    if (last[cc]) {
      root[i] = minu(root[i], last[cc]);
    }
    last[cc] = i;
  }
  for (int i = 1; i <= q; i++) {
    read(li);
    read(ri);
    printf("%d\\n", getsum(root[ri], li, ri));
  }
  return 0;
}
/*
3
12 6
aaabaabaaaab
3 3 4
2 3 2
7 8 3
3 4 2
1 4 2
8 12 1
1 1
a
1 1 1
12 6
aaabaabaaaab
3 3 4
2 3 2
7 8 3
3 4 2
1 4 2
8 12 1
1 1
a
1 1 1
*/


Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
struct Node {
  Node *l, *r;
  int st, ed, sum;
} *root[501001], pool[26040404];
int tot, last[505050];
inline void Build(Node *&now, int st, int ed) {
  now = &pool[++tot];
  now->st = st;
  now->ed = ed;
  now->sum = 0;
  if (st == ed) {
    return;
  }
  int mid = ((st + ed) >> 1);
  Build(now->l, st, mid);
  Build(now->r, mid + 1, ed);
}
inline Node *Add(Node *now, int pos) {
  Node *ret = &pool[++tot];
  ret->st = now->st;
  ret->ed = now->ed;
  ret->sum = now->sum + 1;
  if (now->st == now->ed) {
    return ret;
  }
  if (now->l->ed >= pos) {
    ret->r = now->r;
    ret->l = Add(now->l, pos);
    return ret;
  } else {
    ret->l = now->l;
    ret->r = Add(now->r, pos);
    return ret;
  }
}
inline Node *minu(Node *now, int pos) {
  Node *ret = &pool[++tot];
  ret->st = now->st;
  ret->ed = now->ed;
  ret->sum = now->sum - 1;
  if (now->st == now->ed) {
    return ret;
  }
  if (now->l->ed >= pos) {
    ret->r = now->r;
    ret->l = minu(now->l, pos);
    //	cout << now->st << " " << now->ed << " " << ret->l->sum << endl;
    return ret;
  } else {
    ret->l = now->l;
    ret->r = minu(now->r, pos);
    return ret;
  }
}
inline int getsum(Node *now, int st, int ed) {
  if (now->st > ed || now->ed < st)
    return 0;
  if (now->st >= st && now->ed <= ed) {
    //		cout << now->st << " " << now->ed << " " << st << " " << ed << " " <<
    //now->sum << endl;
    return now->sum;
  }
  return getsum(now->l, st, ed) + getsum(now->r, st, ed);
}
int main() {
  int n;
  int q, li, ri;
  scanf("%d", &n);
  scanf("%d", &q);
  Build(root[0], 1, n);
  int cc;
  for (int i = 1; i <= n; i++) {
    scanf("%d", &cc);
    root[i] = Add(root[i - 1], i);
    if (last[cc]) {
      root[i] = minu(root[i], last[cc]);
    }
    last[cc] = i;
  }
  for (int i = 1; i <= q; i++) {
    scanf("%d%d", &li, &ri);
    printf("%d\\n", getsum(root[ri], li, ri));
  }
  return 0;
}
/*
3
12 6
aaabaabaaaab
3 3 4
2 3 2
7 8 3
3 4 2
1 4 2
8 12 1
1 1
a
1 1 1
12 6
aaabaabaaaab
3 3 4
2 3 2
7 8 3
3 4 2
1 4 2
8 12 1
1 1
a
1 1 1
*/