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

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct event {
  struct QueryEvent *qe;
  struct NumberEvent *ne;
  int type;
};

struct QueryEvent {
  int i, j, ans;
};

struct NumberEvent {
  int num, ind;
};

struct node {
  int l, r, v;
};

int reg[1000001];

struct node *root;

int cmpFun(const void *a, const void *b) {
  struct event *f = (struct event *)a;
  struct event *s = (struct event *)b;
  int r = 0;
  if (f->type == 1) {
    if (s->type == 1) {
      r = f->ne->ind - s->ne->ind;
    } else {
      r = f->ne->ind - s->qe->j;
      if (r == 0)
        r = -1;
    }
  } else if (f->type == 2) {
    if (s->type == 1) {
      r = f->qe->j - s->ne->ind;
      if (r == 0)
        r = 1;
    } else {
      r = f->qe->j - s->qe->j;
    }
  }
  return r;
}

int insert(int start, int end, int index, int pos) {
  if (start == end) {
    root[index].l = 0;
    root[index].r = 0;
    root[index].v = 1;
    return 1;
  }

  int mid = (start + end) / 2;

  if (pos <= mid) {
    int l = insert(start, mid, index * 2 + 1, pos);
    root[index].l = l;
  } else {
    int r = insert(mid + 1, end, index * 2 + 2, pos);
    root[index].r = r;
  }

  return root[index].v = root[index].l + root[index].r;
}

int removee(int start, int end, int del, int index) {
  int pos = del;
  if (start == end) {
    root[index].l = 0;
    root[index].r = 0;
    root[index].v = 0;
    return 0;
  }

  int mid = (start + end) / 2;

  if (pos <= mid) {
    int l = removee(start, mid, del, index * 2 + 1);
    root[index].l = l;
  } else {
    int r = removee(mid + 1, end, del, index * 2 + 2);
    root[index].r = r;
  }

  return root[index].v = root[index].l + root[index].r;
}

int query(int start, int end, int qi, int qj, int index) {
  if (start >= qi && end <= qj) {
    return root[index].v;
  }

  if (qj < start || qi > end) {
    return 0;
  }

  int mid = (start + end) / 2;
  return query(start, mid, qi, qj, index * 2 + 1) +
         query(mid + 1, end, qi, qj, index * 2 + 2);
}

int main() {
  memset(reg, -1, 1000001 * sizeof(int));
  int n, q;
  struct event *events;
  scanf("%d", &n);
  scanf("%d", &q);
  root = (struct node *)malloc(
      sizeof(struct node) *
      (2 * pow(2, ceil(log((double)n) / log((double)2)))));

  events = (struct event *)malloc(sizeof(struct event) * (n + 500000));
  int ind = 0;
  for (int i = 0; i < n; ++i) {
    struct event *e = events + ind++;
    struct NumberEvent *ne =
        (struct NumberEvent *)malloc(sizeof(struct NumberEvent));
    scanf("%d", &ne->num);
    ne->ind = i;
    e->ne = ne;
    e->type = 1;
  }

  struct QueryEvent **original_Queries =
      (struct QueryEvent **)malloc(q * sizeof(struct QueryEvent *));

  for (int i = 0; i < q; ++i) {
    struct event *q = events + ind++;
    struct QueryEvent *e =
        (struct QueryEvent *)malloc(sizeof(struct QueryEvent));
    int a, b;
    scanf("%d%d", &a, &b);
    q->type = 2;
    e->i = a - 1;
    e->j = b - 1;
    q->qe = e;
    original_Queries[i] = e;
  }

  qsort(events, ind, sizeof(struct event), cmpFun);

  for (int i = 0; i < ind; ++i) {
    struct event *e = events + i;
    if (e->type == 1) {
      // Number Event
      if (reg[e->ne->num] == -1) {
        // Not in tree, add
        insert(0, n - 1, 0, e->ne->ind);
        reg[e->ne->num] = e->ne->ind;
      } else {
        int del = reg[e->ne->num];
        // delete this from seg tree
        removee(0, n - 1, del, 0);
        reg[e->ne->num] = e->ne->ind;
        // Add this
        insert(0, n - 1, 0, e->ne->ind);
      }
    } else {
      // Query Event
      int i = e->qe->i;
      int j = e->qe->j;
      int ans = query(0, n - 1, i, j, 0);
      e->qe->ans = ans;
    }
  }

  for (int i = 0; i < q; ++i) {
    printf("%d\\n", original_Queries[i]->ans);
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define _size 500007
#define range 500007
#define numq 500007
using namespace std;
struct dquery {
  int index, x, y;
};
typedef struct dquery dq;
int n, m, A[_size + 10], F[range + 10], ans[numq + 10], _count = 0, block;
dq M[numq + 10];

bool compare(dq a, dq b) {
  if (a.x / block != b.x / block)
    return a.x / block < b.x / block;
  return a.y < b.y;
}
void add(int position) {
  F[A[position]]++;
  if (F[A[position]] == 1)
    _count++;
}
void subtract(int position) {
  F[A[position]]--;
  if (F[A[position]] == 0)
    _count--;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cin >> n >> m;
  block = sqrt(n);
  for (int i = 0; i < n; i++)
    cin >> A[i];
  for (int i = 0; i < m; i++) {
    cin >> M[i].x >> M[i].y;
    M[i].x--;
    M[i].y--;
    M[i].index = i;
  }
  // memset(F,0,sizeof F);
  sort(M, M + m, compare);
  int current_l = 0, current_r = 0, L, R;
  for (int i = 0; i < m; i++) {
    L = M[i].x;
    R = M[i].y;
    while (current_l < L) {
      subtract(current_l);
      current_l++;
    }
    while (current_l > L) {
      add(current_l - 1);
      current_l--;
    }
    while (current_r <= R) {
      add(current_r);
      current_r++;
    }
    while (current_r > R + 1) {
      subtract(current_r - 1);
      current_r--;
    }
    ans[M[i].index] = _count;
  }
  for (int i = 0; i < m; i++)
    cout << ans[i] << "\\n";
}