Problem p01914 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

int rand_int(int a, int b) {
  static random_device rd;
  static mt19937 gen(rd());
  return uniform_int_distribution<int>(a, b)(gen);
}

int z;

struct NodeX {
  using NP = NodeX *;
  NP l = nullptr, r = nullptr;
  int sz;
  int mi;
  void refl() {
    if (l == nullptr) {
      l = new NodeX(sz / 2);
    }
  }
  void refr() {
    if (r == nullptr) {
      r = new NodeX(sz - sz / 2);
    }
  }
  void ref() {
    refl();
    refr();
  }
  int get(int a) { // a <= x && b <= y
    if (a <= 0)
      return mi;
    if (sz <= a)
      return 0;
    int ma = 0;
    if (l != nullptr)
      ma = max(ma, l->get(a));
    if (r != nullptr)
      ma = max(ma, r->get(a - sz / 2));
    return ma;
  }
  void setd(int a, int x) {
    if (sz == 1) {
      mi = max(mi, x);
      return;
    }
    if (a < sz / 2) {
      refl();
      l->setd(a, x);
    } else {
      refr();
      r->setd(a - sz / 2, x);
    }
    mi = 0;
    if (l != nullptr)
      mi = max(mi, l->mi);
    if (r != nullptr)
      mi = max(mi, r->mi);
  }
  NodeX(int sz) : sz(sz) { mi = 0; }
};

struct NodeY {
  using NP = NodeY *;
  NP l, r;
  int sz;
  V<int> fi;
  NodeX *mi;
  void pre(int a, int b) {
    fi.push_back(a);
    if (sz == 1)
      return;
    if (b < sz / 2) {
      l->pre(a, b);
    } else {
      r->pre(a, b - sz / 2);
    }
  }
  void fin() {
    sort(begin(fi), end(fi));
    fi.erase(unique(begin(fi), end(fi)), end(fi));
    mi = new NodeX(int(fi.size()));
    if (sz == 1)
      return;
    l->fin();
    r->fin();
  }
  int get(int a, int b) { // a <= x && b <= y
    if (b <= 0) {
      int aid = lower_bound(begin(fi), end(fi), a) - begin(fi);
      return mi->get(aid);
    }
    if (sz <= b)
      return 0;
    return max(l->get(a, b), r->get(a, b - sz / 2));
  }
  void setd(int a, int b, int x) {
    int aid = lower_bound(begin(fi), end(fi), a) - begin(fi);
    mi->setd(aid, x);

    if (sz == 1)
      return;
    if (b < sz / 2) {
      l->setd(a, b, x);
    } else {
      r->setd(a, b - sz / 2, x);
    }
  }
  NodeY(int sz) : sz(sz) {
    //        mi = new NodeX(z);
    if (sz == 1)
      return;
    l = new NodeY(sz / 2);
    r = new NodeY(sz - sz / 2);
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(20);
  int n;
  cin >> n;
  using P = pair<int, int>;
  V<P> v(n);
  for (int i = 0; i < n; i++) {
    int l, r;
    cin >> l >> r;
    v[i] = P(l, r);
  }
  sort(begin(v), end(v),
       [&](P l, P r) { return l.first + l.second > r.first + r.second; });
  V<int> xv;
  for (int i = 0; i < n; i++) {
    xv.push_back(v[i].first);
    xv.push_back(v[i].second);
  }
  sort(begin(xv), end(xv));
  xv.erase(unique(begin(xv), end(xv)), end(xv));
  for (int i = 0; i < n; i++) {
    v[i].first = lower_bound(begin(xv), end(xv), v[i].first) - begin(xv);
    v[i].second = lower_bound(begin(xv), end(xv), v[i].second) - begin(xv);
  }
  z = int(xv.size()) + 2;

  NodeY *tr = new NodeY(z);
  V<int> a(n);
  int ans = 0;
  for (int i = 0; i < n; i++) {
    auto p = v[i];
    tr->pre(p.second + 1, p.first + 1);
    tr->pre(p.first, p.second);
  }
  tr->fin();
  for (int i = 0; i < n; i++) {
    auto p = v[i];
    auto p2 = P(p.second, p.first);
    a[i] = 1 + tr->get(p.second + 1, p.first + 1);
    tr->setd(p.first, p.second, a[i]);
    ans = max(ans, a[i]);
  }
  cout << ans << endl;
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

int z;

struct NodeX {
  using NP = NodeX *;
  NP l = nullptr, r = nullptr;
  int sz;
  int mi;
  void refl() {
    if (l == nullptr) {
      l = new NodeX(sz / 2);
    }
  }
  void refr() {
    if (r == nullptr) {
      r = new NodeX(sz - sz / 2);
    }
  }
  void ref() {
    refl();
    refr();
  }
  int get(int a) { // a <= x && b <= y
    if (a <= 0)
      return mi;
    if (sz <= a)
      return 0;
    int ma = 0;
    if (l != nullptr)
      ma = max(ma, l->get(a));
    if (r != nullptr)
      ma = max(ma, r->get(a - sz / 2));
    return ma;
  }
  void setd(int a, int x) {
    if (sz == 1) {
      mi = max(mi, x);
      return;
    }
    if (a < sz / 2) {
      refl();
      l->setd(a, x);
    } else {
      refr();
      r->setd(a - sz / 2, x);
    }
    mi = 0;
    if (l != nullptr)
      mi = max(mi, l->mi);
    if (r != nullptr)
      mi = max(mi, r->mi);
  }
  NodeX(int sz) : sz(sz) {
    mi = 0;
    /*        if (sz == 1) return;
            l = new NodeX(sz/2);
            r = new NodeX(sz-sz/2);*/
  }
};

struct NodeY {
  using NP = NodeY *;
  NP l, r;
  int sz;
  NodeX *mi;
  int get(int a, int b) { // a <= x && b <= y
    if (b <= 0)
      return mi->get(a);
    if (sz <= b)
      return 0;
    return max(l->get(a, b), r->get(a, b - sz / 2));
  }
  void setd(int a, int b, int x) {
    mi->setd(a, x);
    if (sz == 1)
      return;
    if (b < sz / 2) {
      l->setd(a, b, x);
    } else {
      r->setd(a, b - sz / 2, x);
    }
  }
  NodeY(int sz) : sz(sz) {
    mi = new NodeX(z);
    if (sz == 1)
      return;
    l = new NodeY(sz / 2);
    r = new NodeY(sz - sz / 2);
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(20);
  int n;
  cin >> n;
  using P = pair<int, int>;
  V<P> v(n);
  for (int i = 0; i < n; i++) {
    int l, r;
    cin >> l >> r;
    v[i] = P(l, r);
  }
  sort(begin(v), end(v),
       [&](P l, P r) { return l.first + l.second > r.first + r.second; });
  V<int> xv;
  for (int i = 0; i < n; i++) {
    xv.push_back(v[i].first);
    xv.push_back(v[i].second);
  }
  sort(begin(xv), end(xv));
  xv.erase(unique(begin(xv), end(xv)), end(xv));
  for (int i = 0; i < n; i++) {
    v[i].first = lower_bound(begin(xv), end(xv), v[i].first) - begin(xv);
    v[i].second = lower_bound(begin(xv), end(xv), v[i].second) - begin(xv);
  }
  z = int(xv.size());

  NodeY *tr = new NodeY(z);
  V<int> a(n);
  int ans = 0;
  for (int i = 0; i < n; i++) {
    auto p = v[i];
    auto p2 = P(p.second, p.first);
    a[i] = 1 + tr->get(p.second + 1, p.first + 1);
    tr->setd(p.first, p.second, a[i]);
    ans = max(ans, a[i]);
  }
  cout << ans << endl;
  return 0;
}