Problem p03061 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <algorithm>
#include <array>
#include <bitset>
#include <cmath>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#define vll vector<ll>
#define vvvl vector<vvl>
#define vvl vector<vector<ll>>
#define VV(a, b, c, d) vector<vector<d>>(a, vector<d>(b, c))
#define VVV(a, b, c, d) vector<vvl>(a, vvl(b, vll(c, d)));
#define re(c, b) for (ll c = 0; c < b; c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
using namespace std;

#define SPLIT 20
template <typename T> struct PersistentArray {
  struct vertex {
    T dat;
    array<vertex *, SPLIT> ch;
    vertex() { ch.fill(nullptr); };
  };
  T zero;
  PersistentArray(){};
  PersistentArray(T z) : zero(z){};
  vertex *root = nullptr;
  ll ver = 0;
  vector<vertex *> version; // 指定したバージョンのルート

  inline vertex *set(ll idx, T x, vertex *par) {

    vertex *now = new vertex();
    if (par) {
      now->ch = par->ch;
      now->dat = par->dat;
    }
    if (idx == 0)
      now->dat = x;
    else
      now->ch[idx % SPLIT] = set(idx / SPLIT, x, now->ch[idx % SPLIT]);
    return now;
  }

  ll update(ll prev, ll idx, T x) {
    vertex *now = set(idx, x, (prev == -1 ? root : version[prev]));
    version.push_back(now);
    return ver++;
  }

  T query(ll prev, ll idx) {
    vertex *now = (prev == -1 ? root : version[prev]);
    if (now == nullptr)
      return zero;
    while (idx) {
      now = now->ch[idx % SPLIT];
      idx /= SPLIT;
      if (now == nullptr)
        return zero;
    }
    return now->dat;
  }
};

template <typename T> struct PersistentSegtree {
  typedef function<T(T, T)> G; // merge
  typedef function<T(T, T)> H; // update
  PersistentArray<T> dat;
  vector<ll> las; // PersistentArrayの最後のバージョン
  ll M = 1, ver = 0;
  G g;
  H h;
  T UNIT;
  PersistentSegtree(ll N, T unit, G merge_func, H update_func) : UNIT(unit) {
    dat = PersistentArray<T>(UNIT);
    g = merge_func;
    h = update_func;
    while (M < N)
      M *= 2;
  }
  inline ll update(ll v, ll k, T x, ll l = 0, ll r = -1) {
    if (r == -1)
      r = M;
    k += M - 1;
    ll array_ver = (v == -1 ? -1 : las[v]);
    ll num = h(dat.query(array_ver, k), x);
    ll idx = dat.update(array_ver, k, num);
    las.push_back(idx);
    while (k > 0) {
      k = (k - 1) / 2;
      T L = dat.query(las[ver], k * 2 + 1);
      T R = dat.query(las[ver], k * 2 + 2);
      num = g(L, R);
      las[ver] = dat.update(las[ver], k, num);
    }
    return ver++;
  }

  T query(ll v, ll a, ll b = -1, ll k = 0, ll l = 0, ll r = -1) {
    if (r == -1)
      r = M;
    if (b == -1)
      b = M;
    if (r <= a || b <= l)
      return UNIT;
    if (a <= l && r <= b)
      return dat.query((v == -1 ? -1 : las[v]), k);
    T A = query(v, a, b, k * 2 + 1, l, (l + r) / 2);
    T B = query(v, a, b, k * 2 + 2, (l + r) / 2, r);
    return g(A, B);
  }
};

ll gcd(ll a, ll b) {
  if (b < a)
    swap(a, b);
  ll r = a % b;
  if (r == 0)
    return b;
  while (r != 0)
    r = a % b, a = b, b = r;
  return a;
}

ll mg(ll l, ll r) {
  if (l == 0)
    return r;
  if (r == 0)
    return l;
  return gcd(l, r);
}
ll upd(ll old, ll nw) { return nw; }

int main() {
  ll n;
  std::cin >> n;
  PersistentSegtree<int> seg(n + 1, 0, mg, upd);
  ll v = -1;

  for (int i = 0; i < n; i++) {
    ll t;
    scanf("%lld", &t);
    v = seg.update(v, i, t);
  }
  ll ans = 0;
  for (int i = 0; i < n; i++) {
    ll L = seg.query(v, 0, i);
    ll R = seg.query(v, i + 1, n);
    ans = max(ans, gcd(L, R));
  }
  std::cout << ans << '\n';
}


Fixed submission:
#include <algorithm>
#include <array>
#include <bitset>
#include <cmath>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#define vll vector<ll>
#define vvvl vector<vvl>
#define vvl vector<vector<ll>>
#define VV(a, b, c, d) vector<vector<d>>(a, vector<d>(b, c))
#define VVV(a, b, c, d) vector<vvl>(a, vvl(b, vll(c, d)));
#define re(c, b) for (ll c = 0; c < b; c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
using namespace std;

#define SPLIT 3
template <typename T> struct PersistentArray {
  struct vertex {
    T dat;
    array<vertex *, SPLIT> ch;
    vertex() { ch.fill(nullptr); };
  };
  T zero;
  PersistentArray(){};
  PersistentArray(T z) : zero(z){};
  vertex *root = nullptr;
  ll ver = 0;
  vector<vertex *> version; // 指定したバージョンのルート

  inline vertex *set(ll idx, T x, vertex *par) {

    vertex *now = new vertex();
    if (par) {
      now->ch = par->ch;
      now->dat = par->dat;
    }
    if (idx == 0)
      now->dat = x;
    else
      now->ch[idx % SPLIT] = set(idx / SPLIT, x, now->ch[idx % SPLIT]);
    return now;
  }

  ll update(ll prev, ll idx, T x) {
    vertex *now = set(idx, x, (prev == -1 ? root : version[prev]));
    version.push_back(now);
    return ver++;
  }

  T query(ll prev, ll idx) {
    vertex *now = (prev == -1 ? root : version[prev]);
    if (now == nullptr)
      return zero;
    while (idx) {
      now = now->ch[idx % SPLIT];
      idx /= SPLIT;
      if (now == nullptr)
        return zero;
    }
    return now->dat;
  }
};

template <typename T> struct PersistentSegtree {
  typedef function<T(T, T)> G; // merge
  typedef function<T(T, T)> H; // update
  PersistentArray<T> dat;
  vector<ll> las; // PersistentArrayの最後のバージョン
  ll M = 1, ver = 0;
  G g;
  H h;
  T UNIT;
  PersistentSegtree(ll N, T unit, G merge_func, H update_func) : UNIT(unit) {
    dat = PersistentArray<T>(UNIT);
    g = merge_func;
    h = update_func;
    while (M < N)
      M *= 2;
  }
  inline ll update(ll v, ll k, T x, ll l = 0, ll r = -1) {
    if (r == -1)
      r = M;
    k += M - 1;
    ll array_ver = (v == -1 ? -1 : las[v]);
    ll num = h(dat.query(array_ver, k), x);
    ll idx = dat.update(array_ver, k, num);
    las.push_back(idx);
    while (k > 0) {
      k = (k - 1) / 2;
      T L = dat.query(las[ver], k * 2 + 1);
      T R = dat.query(las[ver], k * 2 + 2);
      num = g(L, R);
      las[ver] = dat.update(las[ver], k, num);
    }
    return ver++;
  }

  T query(ll v, ll a, ll b = -1, ll k = 0, ll l = 0, ll r = -1) {
    if (r == -1)
      r = M;
    if (b == -1)
      b = M;
    if (r <= a || b <= l)
      return UNIT;
    if (a <= l && r <= b)
      return dat.query((v == -1 ? -1 : las[v]), k);
    T A = query(v, a, b, k * 2 + 1, l, (l + r) / 2);
    T B = query(v, a, b, k * 2 + 2, (l + r) / 2, r);
    return g(A, B);
  }
};

ll gcd(ll a, ll b) {
  if (b < a)
    swap(a, b);
  ll r = a % b;
  if (r == 0)
    return b;
  while (r != 0)
    r = a % b, a = b, b = r;
  return a;
}

ll mg(ll l, ll r) {
  if (l == 0)
    return r;
  if (r == 0)
    return l;
  return gcd(l, r);
}
ll upd(ll old, ll nw) { return nw; }

int main() {
  ll n;
  std::cin >> n;
  PersistentSegtree<int> seg(n + 1, 0, mg, upd);
  ll v = -1;

  for (int i = 0; i < n; i++) {
    ll t;
    scanf("%lld", &t);
    v = seg.update(v, i, t);
  }
  ll ans = 0;
  for (int i = 0; i < n; i++) {
    ll L = seg.query(v, 0, i);
    ll R = seg.query(v, i + 1, n);
    ans = max(ans, gcd(L, R));
  }
  std::cout << ans << '\n';
}