Problem p03667 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

#define range(i, m, n) for (int i = m; i < n; i++)
#define husk(i, m, n) for (int i = m; i > n; i--)

template <typename T> void debug_out(T t) { cerr << t; }

template <typename A, typename B> void debug_out(pair<A, B> u) {
  cerr << "(" << u.first << " " << u.second << ")";
}

template <typename T> void debug_out(vector<T> t) {
  int sz = t.size();
  for (int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if (i != sz - 1)
      cerr << ", ";
  }
}

template <typename T> void debug_out(vector<vector<T>> t) {
  int sz = t.size();
  for (int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if (i != sz - 1)
      cerr << endl;
  }
}

template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) {
  debug_out(H);
  cerr << " ";
  debug_out(T...);
}

template <typename T> void debug_out(set<T> a) {
  vector<T> _a;
  for (T t : a)
    _a.push_back(t);
  debug_out(_a);
}

#define debug(...)                                                             \
  cerr << "[" << #__VA_ARGS__ << "]:" << endl, debug_out(__VA_ARGS__),         \
      cerr << endl;

class segtree {
public:
  struct node {

    int val = 0;

    void apply(int l, int r, int v) { val += v; }
  };

  node unite(const node &a, const node &b) const {
    node res;
    res.val = min(a.val, b.val);
    return res;
  }

  inline void push(int x, int l, int r) {}

  inline void pull(int x, int z) { tree[x] = unite(tree[x + 1], tree[z]); }

  int n;
  vector<node> tree;

  void build(int x, int l, int r) {
    if (l == r) {
      return;
    }
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    build(x + 1, l, y);
    build(z, y + 1, r);
    pull(x, z);
  }

  template <typename M, typename... T>
  void build(int x, int l, int r, const vector<M> &v, const T &...t) {
    if (l == r) {
      tree[x].apply(l, r, v[l], t...);
      return;
    }
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    build(x + 1, l, y, v, t...);
    build(z, y + 1, r, v, t...);
    pull(x, z);
  }

  template <typename M, typename... T>
  segtree(const vector<M> &v, const T &...t) {
    n = v.size();
    assert(n > 0);
    tree.resize(2 * n - 1);
    build(0, 0, n - 1, v, t...);
  }

  segtree(int _n) : n(_n) {
    assert(n > 0);
    tree.resize(2 * n - 1);
    build(0, 0, n - 1);
  }

  segtree(){};

  node get(int x, int l, int r, int ll, int rr) {
    if (ll <= l && r <= rr) {
      return tree[x];
    }
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    push(x, l, r);
    node res{};
    if (rr <= y) {
      res = get(x + 1, l, y, ll, rr);
    } else {
      if (ll > y) {
        res = get(z, y + 1, r, ll, rr);
      } else {
        res = unite(get(x + 1, l, y, ll, rr), get(z, y + 1, r, ll, rr));
      }
    }
    pull(x, z);
    return res;
  }

  node get(int ll, int rr) {
    assert(0 <= ll && ll <= rr && rr <= n - 1);
    return get(0, 0, n - 1, ll, rr);
  }

  node get(int p) {
    assert(0 <= p && p <= n - 1);
    return get(0, 0, n - 1, p, p);
  }

  template <typename... M>
  void modify(int x, int l, int r, int ll, int rr, const M &...v) {
    if (ll <= l && r <= rr) {
      tree[x].apply(l, r, v...);
      return;
    }
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    push(x, l, r);
    if (ll <= y) {
      modify(x + 1, l, y, ll, rr, v...);
    }
    if (rr > y) {
      modify(z, y + 1, r, ll, rr, v...);
    }
    pull(x, z);
  }

  template <typename... M> void modify(int ll, int rr, const M &...v) {
    assert(0 <= ll && ll <= rr && rr <= n - 1);
    modify(0, 0, n - 1, ll, rr, v...);
  }

  // find_first and find_last call all FALSE elements
  // to the left (right) of the sought position exactly once

  int find_first_knowingly(int x, int l, int r,
                           const function<bool(const node &)> &f) {
    if (l == r) {
      return l;
    }
    push(x, l, r);
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    int res;
    if (f(tree[x + 1])) {
      res = find_first_knowingly(x + 1, l, y, f);
    } else {
      res = find_first_knowingly(z, y + 1, r, f);
    }
    pull(x, z);
    return res;
  }

  int find_first(int x, int l, int r, int ll, int rr,
                 const function<bool(const node &)> &f) {
    if (ll <= l && r <= rr) {
      if (!f(tree[x])) {
        return -1;
      }
      return find_first_knowingly(x, l, r, f);
    }
    push(x, l, r);
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    int res = -1;
    if (ll <= y) {
      res = find_first(x + 1, l, y, ll, rr, f);
    }
    if (rr > y && res == -1) {
      res = find_first(z, y + 1, r, ll, rr, f);
    }
    pull(x, z);
    return res;
  }

  int find_first(int ll, int rr, const function<bool(const node &)> &f) {
    assert(0 <= ll && ll <= rr && rr <= n - 1);
    return find_first(0, 0, n - 1, ll, rr, f);
  }

  int find_last_knowingly(int x, int l, int r,
                          const function<bool(const node &)> &f) {
    if (l == r) {
      return l;
    }
    push(x, l, r);
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    int res;
    if (f(tree[z])) {
      res = find_last_knowingly(z, y + 1, r, f);
    } else {
      res = find_last_knowingly(x + 1, l, y, f);
    }
    pull(x, z);
    return res;
  }

  int find_last(int x, int l, int r, int ll, int rr,
                const function<bool(const node &)> &f) {
    if (ll <= l && r <= rr) {
      if (!f(tree[x])) {
        return -1;
      }
      return find_last_knowingly(x, l, r, f);
    }
    push(x, l, r);
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    int res = -1;
    if (rr > y) {
      res = find_last(z, y + 1, r, ll, rr, f);
    }
    if (ll <= y && res == -1) {
      res = find_last(x + 1, l, y, ll, rr, f);
    }
    pull(x, z);
    return res;
  }

  int find_last(int ll, int rr, const function<bool(const node &)> &f) {
    assert(0 <= ll && ll <= rr && rr <= n - 1);
    return find_last(0, 0, n - 1, ll, rr, f);
  }
};

int n, m;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  vector<int> a(n);
  vector<int> cnt(n + 1);
  range(i, 0, n) cin >> a[i];
  range(i, 0, n) cnt[a[i]]++;

  vector<int> foo(n + 1);
  range(i, 0, n + 1) foo[i] = i - cnt[i];
  segtree st(foo);

  set<pair<int, int>> cur;
  range(i, 0, n + 1) {
    int r = i;
    int l = i - cnt[i];
    while (cur.size() && prev(cur.end())->second >= l) {
      l = min(l, prev(cur.end())->first);
      cur.erase(prev(cur.end()));
    }
    l = max(0, l);
    cur.insert(make_pair(l, r));
  }
  int res = 0;
  for (auto i : cur)
    res += i.second - i.first + cnt[i.first];

  while (m--) {
    int x, y;
    cin >> x >> y;
    x--;

    int s = a[x];
    st.modify(s, s, 1);
    int l = s - cnt[s];
    if (l >= 0) {
      int pos = st.find_first(
          l + 1, n, [&](const segtree::node a) { return a.val <= l; });
      if (pos == -1) {
        auto it = cur.lower_bound(make_pair(l + 1, l + 1));
        it--;
        int u = it->first, v = it->second;
        cur.erase(it);
        res -= v - u + cnt[u];
        res += l - u + cnt[u];
        res += v - l - 1 + cnt[l + 1];
        cur.insert(make_pair(u, l));
        cur.insert(make_pair(l + 1, v));
      }
    }

    st.modify(y, y, -1);
    l = y - cnt[y] - !(s == y);
    if (l >= 0) {
      auto it = cur.lower_bound(make_pair(l + 1, l + 1));
      it--;
      if (it->second == l) {
        int u = it->first, v = it->second;
        int uu = next(it)->first, vv = next(it)->second;
        it = cur.erase(it);
        cur.erase(it);
        cur.insert(make_pair(u, vv));
        res += vv - u + cnt[u];
        res -= v - u + cnt[u];
        res -= vv - uu + cnt[uu];
      }
    }

    if (prev(cur.end())->first >= s &&
        cur.lower_bound(make_pair(s, s))->first == s)
      res--;
    if (prev(cur.end())->first >= y &&
        cur.lower_bound(make_pair(y, y))->first == y)
      res++;
    cnt[s]--;
    cnt[y]++;
    res = 0;
    for (auto i : cur)
      res += i.second - i.first + cnt[i.first];
    a[x] = y;
    cout << n - res << "\n";
  }
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>

using namespace std;

#define range(i, m, n) for (int i = m; i < n; i++)
#define husk(i, m, n) for (int i = m; i > n; i--)

template <typename T> void debug_out(T t) { cerr << t; }

template <typename A, typename B> void debug_out(pair<A, B> u) {
  cerr << "(" << u.first << " " << u.second << ")";
}

template <typename T> void debug_out(vector<T> t) {
  int sz = t.size();
  for (int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if (i != sz - 1)
      cerr << ", ";
  }
}

template <typename T> void debug_out(vector<vector<T>> t) {
  int sz = t.size();
  for (int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if (i != sz - 1)
      cerr << endl;
  }
}

template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) {
  debug_out(H);
  cerr << " ";
  debug_out(T...);
}

template <typename T> void debug_out(set<T> a) {
  vector<T> _a;
  for (T t : a)
    _a.push_back(t);
  debug_out(_a);
}

#define debug(...)                                                             \
  cerr << "[" << #__VA_ARGS__ << "]:" << endl, debug_out(__VA_ARGS__),         \
      cerr << endl;

class segtree {
public:
  struct node {

    int val = 0;

    void apply(int l, int r, int v) { val += v; }
  };

  node unite(const node &a, const node &b) const {
    node res;
    res.val = min(a.val, b.val);
    return res;
  }

  inline void push(int x, int l, int r) {}

  inline void pull(int x, int z) { tree[x] = unite(tree[x + 1], tree[z]); }

  int n;
  vector<node> tree;

  void build(int x, int l, int r) {
    if (l == r) {
      return;
    }
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    build(x + 1, l, y);
    build(z, y + 1, r);
    pull(x, z);
  }

  template <typename M, typename... T>
  void build(int x, int l, int r, const vector<M> &v, const T &...t) {
    if (l == r) {
      tree[x].apply(l, r, v[l], t...);
      return;
    }
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    build(x + 1, l, y, v, t...);
    build(z, y + 1, r, v, t...);
    pull(x, z);
  }

  template <typename M, typename... T>
  segtree(const vector<M> &v, const T &...t) {
    n = v.size();
    assert(n > 0);
    tree.resize(2 * n - 1);
    build(0, 0, n - 1, v, t...);
  }

  segtree(int _n) : n(_n) {
    assert(n > 0);
    tree.resize(2 * n - 1);
    build(0, 0, n - 1);
  }

  segtree(){};

  node get(int x, int l, int r, int ll, int rr) {
    if (ll <= l && r <= rr) {
      return tree[x];
    }
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    push(x, l, r);
    node res{};
    if (rr <= y) {
      res = get(x + 1, l, y, ll, rr);
    } else {
      if (ll > y) {
        res = get(z, y + 1, r, ll, rr);
      } else {
        res = unite(get(x + 1, l, y, ll, rr), get(z, y + 1, r, ll, rr));
      }
    }
    pull(x, z);
    return res;
  }

  node get(int ll, int rr) {
    assert(0 <= ll && ll <= rr && rr <= n - 1);
    return get(0, 0, n - 1, ll, rr);
  }

  node get(int p) {
    assert(0 <= p && p <= n - 1);
    return get(0, 0, n - 1, p, p);
  }

  template <typename... M>
  void modify(int x, int l, int r, int ll, int rr, const M &...v) {
    if (ll <= l && r <= rr) {
      tree[x].apply(l, r, v...);
      return;
    }
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    push(x, l, r);
    if (ll <= y) {
      modify(x + 1, l, y, ll, rr, v...);
    }
    if (rr > y) {
      modify(z, y + 1, r, ll, rr, v...);
    }
    pull(x, z);
  }

  template <typename... M> void modify(int ll, int rr, const M &...v) {
    assert(0 <= ll && ll <= rr && rr <= n - 1);
    modify(0, 0, n - 1, ll, rr, v...);
  }

  // find_first and find_last call all FALSE elements
  // to the left (right) of the sought position exactly once

  int find_first_knowingly(int x, int l, int r,
                           const function<bool(const node &)> &f) {
    if (l == r) {
      return l;
    }
    push(x, l, r);
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    int res;
    if (f(tree[x + 1])) {
      res = find_first_knowingly(x + 1, l, y, f);
    } else {
      res = find_first_knowingly(z, y + 1, r, f);
    }
    pull(x, z);
    return res;
  }

  int find_first(int x, int l, int r, int ll, int rr,
                 const function<bool(const node &)> &f) {
    if (ll <= l && r <= rr) {
      if (!f(tree[x])) {
        return -1;
      }
      return find_first_knowingly(x, l, r, f);
    }
    push(x, l, r);
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    int res = -1;
    if (ll <= y) {
      res = find_first(x + 1, l, y, ll, rr, f);
    }
    if (rr > y && res == -1) {
      res = find_first(z, y + 1, r, ll, rr, f);
    }
    pull(x, z);
    return res;
  }

  int find_first(int ll, int rr, const function<bool(const node &)> &f) {
    assert(0 <= ll && ll <= rr && rr <= n - 1);
    return find_first(0, 0, n - 1, ll, rr, f);
  }

  int find_last_knowingly(int x, int l, int r,
                          const function<bool(const node &)> &f) {
    if (l == r) {
      return l;
    }
    push(x, l, r);
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    int res;
    if (f(tree[z])) {
      res = find_last_knowingly(z, y + 1, r, f);
    } else {
      res = find_last_knowingly(x + 1, l, y, f);
    }
    pull(x, z);
    return res;
  }

  int find_last(int x, int l, int r, int ll, int rr,
                const function<bool(const node &)> &f) {
    if (ll <= l && r <= rr) {
      if (!f(tree[x])) {
        return -1;
      }
      return find_last_knowingly(x, l, r, f);
    }
    push(x, l, r);
    int y = (l + r) >> 1;
    int z = x + ((y - l + 1) << 1);
    int res = -1;
    if (rr > y) {
      res = find_last(z, y + 1, r, ll, rr, f);
    }
    if (ll <= y && res == -1) {
      res = find_last(x + 1, l, y, ll, rr, f);
    }
    pull(x, z);
    return res;
  }

  int find_last(int ll, int rr, const function<bool(const node &)> &f) {
    assert(0 <= ll && ll <= rr && rr <= n - 1);
    return find_last(0, 0, n - 1, ll, rr, f);
  }
};

int n, m;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  vector<int> a(n);
  vector<int> cnt(n + 1);
  range(i, 0, n) cin >> a[i];
  range(i, 0, n) cnt[a[i]]++;

  vector<int> foo(n + 1);
  range(i, 0, n + 1) foo[i] = i - cnt[i];
  segtree st(foo);

  set<pair<int, int>> cur;
  range(i, 0, n + 1) {
    int r = i;
    int l = i - cnt[i];
    while (cur.size() && prev(cur.end())->second >= l) {
      l = min(l, prev(cur.end())->first);
      cur.erase(prev(cur.end()));
    }
    l = max(0, l);
    cur.insert(make_pair(l, r));
  }
  int res = 0;
  for (auto i : cur)
    res += i.second - i.first + cnt[i.first];

  while (m--) {
    int x, y;
    cin >> x >> y;
    x--;

    int s = a[x];
    st.modify(s, s, 1);
    int l = s - cnt[s];
    if (l >= 0) {
      int pos = st.find_first(
          l + 1, n, [&](const segtree::node a) { return a.val <= l; });
      if (pos == -1) {
        auto it = cur.lower_bound(make_pair(l + 1, l + 1));
        it--;
        int u = it->first, v = it->second;
        cur.erase(it);
        res -= v - u + cnt[u];
        res += l - u + cnt[u];
        res += v - l - 1 + cnt[l + 1];
        cur.insert(make_pair(u, l));
        cur.insert(make_pair(l + 1, v));
      }
    }

    st.modify(y, y, -1);
    l = y - cnt[y] - !(s == y);
    if (l >= 0) {
      auto it = cur.lower_bound(make_pair(l + 1, l + 1));
      it--;
      if (it->second == l) {
        int u = it->first, v = it->second;
        int uu = next(it)->first, vv = next(it)->second;
        it = cur.erase(it);
        cur.erase(it);
        cur.insert(make_pair(u, vv));
        res += vv - u + cnt[u];
        res -= v - u + cnt[u];
        res -= vv - uu + cnt[uu];
      }
    }

    if (prev(cur.end())->first >= s &&
        cur.lower_bound(make_pair(s, s))->first == s)
      res--;
    if (prev(cur.end())->first >= y &&
        cur.lower_bound(make_pair(y, y))->first == y)
      res++;
    cnt[s]--;
    cnt[y]++;
    a[x] = y;
    cout << n - res << "\n";
  }
  return 0;
}