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

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
using ll = long long;

template <typename T = int, const T U = (T)1 << (T)30> class vEB {
  const T ctz;
  struct node {
    T min, max;
    node *summary;
    unordered_map<T, node *> cluster;
    node() : min(U), max(-1), summary(nullptr) {}
  } *root;
  int cnt;

private:
  T downsqrt(T ub) const { return ub >> (T)1; }
  T upsqrt(T ub) const { return (ub + 1) >> (T)1; }
  T high(T x, T ub) const { return x >> downsqrt(ub); }
  T low(T x, T ub) const { return x & (((T)1 << downsqrt(ub)) - 1); }
  T index(T x, T y, T ub) const { return (x << downsqrt(ub)) + y; }
  T minimum(node *v) const { return v ? v->min : U; }
  T maximum(node *v) const { return v ? v->max : -1; }
  bool member(node *v, T x, T ub) const {
    if (!v)
      return false;
    if (v->min == x || v->max == x)
      return true;
    if (v->cluster.empty())
      return false;
    return member(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
  }
  node *empty_insert(node *v, T x, T ub) {
    if (!v)
      v = new node();
    v->min = v->max = x;
    return v;
  }
  node *insert(node *v, T x, T ub) {
    if (!v)
      v = new node();
    if (v->min == U) {
      empty_insert(v, x, ub);
      return v;
    }
    if (x < v->min)
      swap(x, v->min);
    if (ub > 1) {
      if (minimum(v->cluster[high(x, ub)]) == U) {
        v->summary = insert(v->summary, high(x, ub), upsqrt(ub));
        v->cluster[high(x, ub)] =
            empty_insert(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
      } else {
        v->cluster[high(x, ub)] =
            insert(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
      }
    }
    if (x > v->max)
      v->max = x;
    return v;
  }
  node *erase(node *v, T x, T ub) {
    if (v->min == v->max) {
      v->min = U;
      v->max = -1;
      return nullptr;
    }
    if (ub <= 1) {
      v->max = v->min = (x == 0);
      return v;
    }
    if (x == v->min) {
      T first_cluster = minimum(v->summary);
      v->min = x = index(first_cluster, minimum(v->cluster[first_cluster]), ub);
    }
    v->cluster[high(x, ub)] =
        erase(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
    if (minimum(v->cluster[high(x, ub)]) == U) {
      v->summary = erase(v->summary, high(x, ub), upsqrt(ub));
      if (x == v->max) {
        T summary_max = maximum(v->summary);
        if (summary_max == -1) {
          v->max = v->min;
        } else {
          v->max = index(summary_max, maximum(v->cluster[summary_max]), ub);
        }
      }
    } else if (x == v->max) {
      v->max = index(high(x, ub), maximum(v->cluster[high(x, ub)]), ub);
    }
    return v;
  }
  T successor(node *v, T x, T ub) const {
    if (!v)
      return U;
    if (ub <= 1) {
      if (x == 0 && v->max == 1)
        return 1;
      return U;
    }
    if (v->min != U && x < v->min)
      return v->min;
    T max_low = maximum(v->cluster[high(x, ub)]);
    if (max_low != -1 && low(x, ub) < max_low) {
      return index(high(x, ub),
                   successor(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub)),
                   ub);
    }
    T succ_cluster = successor(v->summary, high(x, ub), upsqrt(ub));
    if (succ_cluster == U)
      return U;
    return index(succ_cluster, minimum(v->cluster[succ_cluster]), ub);
  }
  T predecessor(node *v, T x, T ub) const {
    if (!v)
      return -1;
    if (ub <= 1) {
      if (x == 1 && v->min == 0)
        return 0;
      return -1;
    }
    if (v->max != -1 && x > v->max)
      return v->max;
    T min_low = minimum(v->cluster[high(x, ub)]);
    if (min_low != U && low(x, ub) > min_low) {
      return index(
          high(x, ub),
          predecessor(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub)), ub);
    }
    T pred_cluster = predecessor(v->summary, high(x, ub), upsqrt(ub));
    if (pred_cluster == -1) {
      if (v->min != U && x > v->min)
        return v->min;
      return -1;
    }
    return index(pred_cluster, maximum(v->cluster[pred_cluster]), ub);
  }
  T get_ctz(T x) {
    T tmp = 1, res = 0;
    while (tmp < x) {
      tmp <<= (T)1;
      res++;
    }
    return res;
  }

public:
  vEB() : ctz(get_ctz(U)), root(nullptr), cnt(0) {}
  int size() const { return cnt; }
  bool member(T x) const { return member(root, x, ctz); }
  T minimum() const { return minimum(root); }
  T maximum() const { return maximum(root); }
  void insert(T x) {
    if (!member(x))
      root = insert(root, x, ctz), cnt++;
  }
  void erase(T x) {
    if (member(x))
      root = erase(root, x, ctz), cnt--;
  }
  T successor(T x) const { return successor(root, x, ctz); }
  T predecessor(T x) const { return predecessor(root, x, ctz); }
};

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n;
  cin >> n;
  vEB<ll, 1ll << 62ll> veb;
  for (int i = 0; i < n; i++) {
    int x;
    cin >> x;
    veb.insert(x);
  }
  int q, res = 0;
  cin >> q;
  while (q--) {
    int x;
    cin >> x;
    res += veb.member(x);
  }
  cout << res << endl;
  return 0;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

template <typename T = int, const T U = (T)1 << (T)30> class vEB {
  const T ctz;
  struct node {
    T min, max;
    node *summary, **cluster;
    node() : min(U), max(-1), summary(nullptr), cluster(nullptr) {}
  } *root;
  int cnt;

private:
  T downsqrt(T ub) const { return ub >> (T)1; }
  T upsqrt(T ub) const { return (ub + 1) >> (T)1; }
  T high(T x, T ub) const { return x >> downsqrt(ub); }
  T low(T x, T ub) const { return x & (((T)1 << downsqrt(ub)) - 1); }
  T index(T x, T y, T ub) const { return (x << downsqrt(ub)) + y; }
  T minimum(node *v) const { return v ? v->min : U; }
  T maximum(node *v) const { return v ? v->max : -1; }
  bool member(node *v, T x, T ub) const {
    if (!v)
      return false;
    if (v->min == x || v->max == x)
      return true;
    if (!v->cluster)
      return false;
    return member(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
  }
  node *new_node(T ub) {
    node *v = new node();
    if (ub > 1) {
      T sz = (T)1 << upsqrt(ub);
      v->cluster = new node *[sz];
      for (int i = 0; i < sz; i++) {
        v->cluster[i] = nullptr;
      }
    }
    return v;
  }
  node *empty_insert(node *v, T x, T ub) {
    if (!v)
      v = new_node(ub);
    v->min = v->max = x;
    return v;
  }
  node *insert(node *v, T x, T ub) {
    if (!v)
      v = new_node(ub);
    if (v->min == U) {
      empty_insert(v, x, ub);
      return v;
    }
    if (x < v->min)
      swap(x, v->min);
    if (ub > 1) {
      if (minimum(v->cluster[high(x, ub)]) == U) {
        v->summary = insert(v->summary, high(x, ub), upsqrt(ub));
        v->cluster[high(x, ub)] =
            empty_insert(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
      } else {
        v->cluster[high(x, ub)] =
            insert(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
      }
    }
    if (x > v->max)
      v->max = x;
    return v;
  }
  node *erase(node *v, T x, T ub) {
    if (v->min == v->max) {
      v->min = U;
      v->max = -1;
      return nullptr;
    }
    if (ub <= 1) {
      v->max = v->min = (x == 0);
      return v;
    }
    if (x == v->min) {
      T first_cluster = minimum(v->summary);
      v->min = x = index(first_cluster, minimum(v->cluster[first_cluster]), ub);
    }
    v->cluster[high(x, ub)] =
        erase(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
    if (minimum(v->cluster[high(x, ub)]) == U) {
      v->summary = erase(v->summary, high(x, ub), upsqrt(ub));
      if (x == v->max) {
        T summary_max = maximum(v->summary);
        if (summary_max == -1) {
          v->max = v->min;
        } else {
          v->max = index(summary_max, maximum(v->cluster[summary_max]), ub);
        }
      }
    } else if (x == v->max) {
      v->max = index(high(x, ub), maximum(v->cluster[high(x, ub)]), ub);
    }
    return v;
  }
  T successor(node *v, T x, T ub) const {
    if (!v)
      return U;
    if (ub <= 1) {
      if (x == 0 && v->max == 1)
        return 1;
      return U;
    }
    if (v->min != U && x < v->min)
      return v->min;
    T max_low = maximum(v->cluster[high(x, ub)]);
    if (max_low != -1 && low(x, ub) < max_low) {
      return index(high(x, ub),
                   successor(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub)),
                   ub);
    }
    T succ_cluster = successor(v->summary, high(x, ub), upsqrt(ub));
    if (succ_cluster == U)
      return U;
    return index(succ_cluster, minimum(v->cluster[succ_cluster]), ub);
  }
  T predecessor(node *v, T x, T ub) const {
    if (!v)
      return -1;
    if (ub <= 1) {
      if (x == 1 && v->min == 0)
        return 0;
      return -1;
    }
    if (v->max != -1 && x > v->max)
      return v->max;
    T min_low = minimum(v->cluster[high(x, ub)]);
    if (min_low != U && low(x, ub) > min_low) {
      return index(
          high(x, ub),
          predecessor(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub)), ub);
    }
    T pred_cluster = predecessor(v->summary, high(x, ub), upsqrt(ub));
    if (pred_cluster == -1) {
      if (v->min != U && x > v->min)
        return v->min;
      return -1;
    }
    return index(pred_cluster, maximum(v->cluster[pred_cluster]), ub);
  }
  T get_ctz(T x) {
    T tmp = 1, res = 0;
    while (tmp < x) {
      tmp <<= (T)1;
      res++;
    }
    return res;
  }

public:
  vEB() : ctz(get_ctz(U)), root(nullptr), cnt(0) {}
  int size() const { return cnt; }
  bool member(T x) const { return member(root, x, ctz); }
  T minimum() const { return minimum(root); }
  T maximum() const { return maximum(root); }
  void insert(T x) {
    if (!member(x))
      root = insert(root, x, ctz), cnt++;
  }
  void erase(T x) {
    if (member(x))
      root = erase(root, x, ctz), cnt--;
  }
  T successor(T x) const { return successor(root, x, ctz); }
  T predecessor(T x) const { return predecessor(root, x, ctz); }
};

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n;
  cin >> n;
  vEB<ll, 1ll << 50ll> veb;
  for (int i = 0; i < n; i++) {
    int x;
    cin >> x;
    veb.insert(x);
  }
  int q, res = 0;
  cin >> q;
  while (q--) {
    int x;
    cin >> x;
    res += veb.member(x);
  }
  cout << res << endl;
  return 0;
}