Problem p02599 (C++)

Buggy submission (status: Runtime Error):
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < n; i++)
#define cinf(n, x)                                                             \
  for (int i = 0; i < (n); i++)                                                \
    cin >> x[i];
#define ft first
#define sc second
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(), (v).end()
#define LB(a, x) lb(all(a), x) - a.begin()
#define UB(a, x) ub(all(a), x) - a.begin()
#define mod 1000000007
#define FS fixed << setprecision(15)
using namespace std;
typedef long long ll;
const double pi = 3.141592653589793;
template <class T> using V = vector<T>;
using Graph = vector<vector<int>>;
using P = pair<ll, ll>;
typedef unsigned long long ull;
typedef long double ldouble;
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

const ll INF = 1e18;
const int mx = 200005;

class Segtree {
public:
  ll N = 1;
  ll MX = 2000000;
  V<ll> dat;
  explicit Segtree(ll sz) {
    while (N < sz)
      N *= 2;
  }

  // Range Minimum Query -------------------------

  void min_init() {
    for (int i = 0; i < N; i++)
      min_update(i, INF);
  }

  void min_update(ll k, ll a) {
    k += N - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = min(dat[2 * k + 1], dat[2 * k + 2]);
    }
  }

  ll min_query(ll a, ll b, ll k, ll l, ll r) {
    if (r <= a || b <= l)
      return INF;
    if (a <= l && r <= b)
      return dat[k];
    ll m = (l + r) / 2;
    ll u = min_query(a, b, 2 * k + 1, l, m);
    ll v = min_query(a, b, 2 * k + 2, m, r);
    return min(u, v);
  }

  // Range Maximum Query ---------------------------

  void max_init() {
    for (int i = 0; i < N; i++)
      max_update(i, -INF);
  }

  void max_update(ll k, ll a) {
    k += N - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = max(dat[2 * k + 1], dat[2 * k + 2]);
    }
  }

  ll max_query(ll a, ll b, ll k, ll l, ll r) {
    if (r <= a || b <= l)
      return -INF;
    if (a <= l && r <= b)
      return dat[k];
    ll m = (l + r) / 2;
    ll u = max_query(a, b, 2 * k + 1, l, m);
    ll v = max_query(a, b, 2 * k + 2, m, r);
    return max(u, v);
  }

  // Range Sum Query -----------------------------

  void sum_update(ll k, ll a) {
    k += N - 1;
    dat[k] += a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = (dat[2 * k + 1] + dat[2 * k + 2]);
    }
  }

  ll sum_query(ll a, ll b, ll k, ll l, ll r) {
    if (r <= a || b <= l)
      return 0LL;
    if (a <= l && r <= b)
      return dat[k];
    ll m = (l + r) / 2;
    ll u = sum_query(a, b, 2 * k + 1, l, m);
    ll v = sum_query(a, b, 2 * k + 2, m, r);
    return (u + v);
  }

  // その他----------------------------------------
  /*
  ll unit(){
      return ;//単位元
  }
  ll calc(ll a,ll b){
      return ;//演算
  }
  void update(ll k,ll a){
      k+=N-1;
      dat[k]=a;
      while(k>0){
          k=(k-1)/2;
          dat[k]=calc(dat[2*k+1],dat[2*k+2]);
      }
  }
  ll query(ll a,ll b,ll k,ll l,ll r){
      if(r<=a||b<=l)return unit();
      if(a<=l&&r<=b)return dat[k];
      ll m=(l+r)/2;
      ll u=min_query(a,b,2*k+1,l,m);
      ll v=min_query(a,b,2*k+2,m,r);
      return calc(u,v);
  }
  */
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll n, qq;
  cin >> n >> qq;
  V<ll> c(n);
  Segtree stree(n);
  V<ll> last(n, -1);
  rep(i, n) {
    cin >> c[i];
    c[i]--;
  }
  V<pair<P, ll>> p(qq);
  rep(i, qq) {
    ll l, r;
    cin >> l >> r;
    l--;
    r--;
    p[i] = make_pair(make_pair(r, l), i);
    // cout<<how[r]+rhow[l]-M<<'\n';
  }
  sort(all(p));
  V<ll> ans(qq);
  ll pos = 0;
  rep(i, qq) {
    for (int j = pos; j <= p[i].ft.ft; j++) {
      stree.sum_update(j, 1);
      if (last[c[j]] != -1)
        stree.sum_update(last[c[j]], -1);
      last[c[j]] = j;
    }
    ans[p[i].sc] = stree.sum_query(p[i].ft.sc, p[i].ft.ft + 1, 0, 0, stree.N);
    pos = p[i].ft.ft + 1;
  }
  rep(i, qq) cout << ans[i] << '\n';
}
// ペナルティ出しても焦らない　ACできると信じろ！！！
// どうしてもわからないときはサンプルで実験　何か見えてくるかも
// 頭で考えてダメなら紙におこせ！！
/*
V,P(大文字)使用不可
乗算などの際にオーバーフローに注意せよ！
(適切にmodをとれ　にぶたんで途中で切り上げろ)
制約をよく読め！
{
    ・全探索できるなら全探索しろ
    ・異常な制約ならそこに注目
}
stringの計算量(扱い)注意
コーナー注意！(特に数値が小さいものについては要検証)
N行出力のときは'¥n'
グリッド上では行先が範囲内におさまるかif文で確認(RE注意)
if文ではちゃんと比較演算子==を使え('='でもエラー出ない)
配列(vector)の大きさが0か1以上かで場合分けせよ(RE注意)
(vector<int> a(m)でm==0というものはできない)
modはなるべく最後に取れ！
doubleを扱うときには(abs)ではなく'fabs'!!!
*/

Fixed submission:
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < n; i++)
#define cinf(n, x)                                                             \
  for (int i = 0; i < (n); i++)                                                \
    cin >> x[i];
#define ft first
#define sc second
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(), (v).end()
#define LB(a, x) lb(all(a), x) - a.begin()
#define UB(a, x) ub(all(a), x) - a.begin()
#define mod 1000000007
#define FS fixed << setprecision(15)
using namespace std;
typedef long long ll;
const double pi = 3.141592653589793;
template <class T> using V = vector<T>;
using Graph = vector<vector<int>>;
using P = pair<ll, ll>;
typedef unsigned long long ull;
typedef long double ldouble;
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

const ll INF = 1e18;
const int mx = 200005;

class Segtree {
public:
  ll N = 1;
  ll MX = 2000000;
  V<ll> dat;
  explicit Segtree(ll sz) {
    while (N < sz)
      N *= 2;
    dat.reserve(2 * N);
  }

  // Range Minimum Query -------------------------

  void min_init() {
    for (int i = 0; i < N; i++)
      min_update(i, INF);
  }

  void min_update(ll k, ll a) {
    k += N - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = min(dat[2 * k + 1], dat[2 * k + 2]);
    }
  }

  ll min_query(ll a, ll b, ll k, ll l, ll r) {
    if (r <= a || b <= l)
      return INF;
    if (a <= l && r <= b)
      return dat[k];
    ll m = (l + r) / 2;
    ll u = min_query(a, b, 2 * k + 1, l, m);
    ll v = min_query(a, b, 2 * k + 2, m, r);
    return min(u, v);
  }

  // Range Maximum Query ---------------------------

  void max_init() {
    for (int i = 0; i < N; i++)
      max_update(i, -INF);
  }

  void max_update(ll k, ll a) {
    k += N - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = max(dat[2 * k + 1], dat[2 * k + 2]);
    }
  }

  ll max_query(ll a, ll b, ll k, ll l, ll r) {
    if (r <= a || b <= l)
      return -INF;
    if (a <= l && r <= b)
      return dat[k];
    ll m = (l + r) / 2;
    ll u = max_query(a, b, 2 * k + 1, l, m);
    ll v = max_query(a, b, 2 * k + 2, m, r);
    return max(u, v);
  }

  // Range Sum Query -----------------------------

  void sum_update(ll k, ll a) {
    k += N - 1;
    dat[k] += a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = (dat[2 * k + 1] + dat[2 * k + 2]);
    }
  }

  ll sum_query(ll a, ll b, ll k, ll l, ll r) {
    if (r <= a || b <= l)
      return 0LL;
    if (a <= l && r <= b)
      return dat[k];
    ll m = (l + r) / 2;
    ll u = sum_query(a, b, 2 * k + 1, l, m);
    ll v = sum_query(a, b, 2 * k + 2, m, r);
    return (u + v);
  }

  // その他----------------------------------------
  /*
  ll unit(){
      return ;//単位元
  }
  ll calc(ll a,ll b){
      return ;//演算
  }
  void update(ll k,ll a){
      k+=N-1;
      dat[k]=a;
      while(k>0){
          k=(k-1)/2;
          dat[k]=calc(dat[2*k+1],dat[2*k+2]);
      }
  }
  ll query(ll a,ll b,ll k,ll l,ll r){
      if(r<=a||b<=l)return unit();
      if(a<=l&&r<=b)return dat[k];
      ll m=(l+r)/2;
      ll u=min_query(a,b,2*k+1,l,m);
      ll v=min_query(a,b,2*k+2,m,r);
      return calc(u,v);
  }
  */
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll n, qq;
  cin >> n >> qq;
  V<ll> c(n);
  Segtree stree(n);
  V<ll> last(n, -1);
  rep(i, n) {
    cin >> c[i];
    c[i]--;
  }
  V<pair<P, ll>> p(qq);
  rep(i, qq) {
    ll l, r;
    cin >> l >> r;
    l--;
    r--;
    p[i] = make_pair(make_pair(r, l), i);
    // cout<<how[r]+rhow[l]-M<<'\n';
  }
  sort(all(p));
  V<ll> ans(qq);
  ll pos = 0;
  rep(i, qq) {
    for (int j = pos; j <= p[i].ft.ft; j++) {
      stree.sum_update(j, 1);
      if (last[c[j]] != -1)
        stree.sum_update(last[c[j]], -1);
      last[c[j]] = j;
    }
    ans[p[i].sc] = stree.sum_query(p[i].ft.sc, p[i].ft.ft + 1, 0, 0, stree.N);
    pos = p[i].ft.ft + 1;
  }
  rep(i, qq) cout << ans[i] << '\n';
}
// ペナルティ出しても焦らない　ACできると信じろ！！！
// どうしてもわからないときはサンプルで実験　何か見えてくるかも
// 頭で考えてダメなら紙におこせ！！
/*
V,P(大文字)使用不可
乗算などの際にオーバーフローに注意せよ！
(適切にmodをとれ　にぶたんで途中で切り上げろ)
制約をよく読め！
{
    ・全探索できるなら全探索しろ
    ・異常な制約ならそこに注目
}
stringの計算量(扱い)注意
コーナー注意！(特に数値が小さいものについては要検証)
N行出力のときは'¥n'
グリッド上では行先が範囲内におさまるかif文で確認(RE注意)
if文ではちゃんと比較演算子==を使え('='でもエラー出ない)
配列(vector)の大きさが0か1以上かで場合分けせよ(RE注意)
(vector<int> a(m)でm==0というものはできない)
modはなるべく最後に取れ！
doubleを扱うときには(abs)ではなく'fabs'!!!
*/