Problem p03641 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_poizcy.hpp>
typedef long long ll;
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define mem(a, h) memset(a, (h), sizeof(a))
#define fi first
#define se second
#define por(a, b) (((a % MOD) * (b % MOD)) % MOD)
#define forg(i, b, e, c) for (ll i = (ll)b; i < (ll)e; i += c)
#define forr(i, b, e) for (ll i = b; i < e; i++)

using namespace std;
// using namespace __gnu_pbds;
typedef double lldb;
typedef pair<int, int> ii;
typedef pair<double, double> iidb;
#define iii pair<ii, nodo *>
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;
typedef vector<ll> vll;
// typedef
// tree<ii,null_type,less<ii>,rb_tree_tag,tree_order_statistics_node_update>
// ordered_set;
const ll INF = 1e9 + 7;
const double PI = acos(-1);
#define initseg ll new_nodo = (pnodo * 2), mid = (iz + der) / 2;

// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define tam 6001000
#define offset 3000
#define ptr nodo *

using namespace std;
struct nodo {
  ptr iz;
  ptr der;
  ptr mid;
  ii valor;
};
nodo nodos[tam];
int cuniv = 0;
ptr getnodo() { return &nodos[cuniv++]; }

int v[tam], n;
const int cmplog = 18;

int sp[2][cmplog][tam];
int lstsparce[tam];
void initsp() {
  forr(par, 0, 2) forr(bit, 0, cmplog) forr(pos, 0, tam) sp[par][bit][pos] =
      INF;
  forr(i, 0, 2) {
    forg(j, i, n, 2) { sp[i][0][j] = v[j]; }
    /*	<<"par "<<i<<endl;
            forr(j,0,n+3)
            {
                    <<sp[i][0][j]<<" ";
            }
            <<endl;*/
  }
  forr(par, 0, 2) {
    forr(bit, 1, cmplog) {
      forr(pos, 0, n) {
        sp[par][bit][pos] = min(sp[par][bit - 1][pos],
                                sp[par][bit - 1][pos + (1 << (bit - 1))]);
      }
      /*<<"par "<<par<<endl;
      forr(j,0,n+3)
      {
              <<sp[par][bit][j]<<" ";
      }
      <<endl;*/
    }
    //<<endl;
  }
  lstsparce[1] = 0;
  forr(i, 2, tam) lstsparce[i] = lstsparce[i / 2] + 1;
}
int getquery(int iz, int der) {
  int par = (iz % 2);
  int delta = (der - iz + 1);
  int bit = lstsparce[delta];
  return min(sp[par][bit][iz], sp[par][bit][der - (1 << bit) + 1]);
}
int vpos[tam];
void divide(ptr nodo, int iz, int der) {
  if (iz > der)
    return;
  //<<iz<<' '<<der<<endl;
  assert((der - iz + 1) % 2 == 0);

  if (der - iz + 1 == 2) {
    nodo->valor = {v[iz], v[der]};
    return;
  }
  int li = vpos[getquery(iz, der)];
  int ri = vpos[getquery(li + 1, der)];
  //<<li<<' '<<ri<<endl;
  nodo->valor = {v[li], v[ri]};

  nodo->iz = getnodo();
  nodo->iz->valor = {-1, -1};
  nodo->mid = getnodo();
  nodo->mid->valor = {-1, -1};
  nodo->der = getnodo();
  nodo->der->valor = {-1, -1};
  divide(nodo->iz, iz, li - 1);
  divide(nodo->mid, li + 1, ri - 1);
  divide(nodo->der, ri + 1, der);
}

int main() {

  forr(i, 0, tam) nodos[i].iz = nodos[i].der = nodos[i].mid = NULL;

  cin >> n;
  forr(i, 0, n) {
    cin >> v[i];
    vpos[v[i]] = i;
  }
  initsp();
  ptr root;
  priority_queue<iii, vector<iii>, greater<iii>> cola;

  root = getnodo();
  divide(root, 0, n - 1);
  // return 0;
  cola.push({root->valor, root});
  while (!cola.empty()) {
    auto par = cola.top();
    cola.pop();
    ptr cual = par.se;
    cout << par.fi.fi << ' ' << par.fi.se << ' ';
    if (cual->iz && cual->iz->valor.fi != -1)
      cola.push({cual->iz->valor, cual->iz});

    if (cual->mid && cual->mid->valor.fi != -1)
      cola.push({cual->mid->valor, cual->mid});

    if (cual->der && cual->der->valor.fi != -1)
      cola.push({cual->der->valor, cual->der});
  }
}

Fixed submission:
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_poizcy.hpp>
typedef long long ll;
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define mem(a, h) memset(a, (h), sizeof(a))
#define fi first
#define se second
#define por(a, b) (((a % MOD) * (b % MOD)) % MOD)
#define forg(i, b, e, c) for (ll i = (ll)b; i < (ll)e; i += c)
#define forr(i, b, e) for (ll i = b; i < e; i++)

using namespace std;
// using namespace __gnu_pbds;
typedef double lldb;
typedef pair<int, int> ii;
typedef pair<double, double> iidb;
#define iii pair<ii, nodo *>
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;
typedef vector<ll> vll;
// typedef
// tree<ii,null_type,less<ii>,rb_tree_tag,tree_order_statistics_node_update>
// ordered_set;
const ll INF = 1e9 + 7;
const double PI = acos(-1);
#define initseg ll new_nodo = (pnodo * 2), mid = (iz + der) / 2;

// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define tam 1001000
#define offset 3000
#define ptr nodo *

using namespace std;
struct nodo {
  ptr iz;
  ptr der;
  ptr mid;
  ii valor;
};
nodo nodos[tam];
int cuniv = 0;
ptr getnodo() { return &nodos[cuniv++]; }

int v[tam], n;
const int cmplog = 18;

int sp[2][cmplog][tam];
int lstsparce[tam];
void initsp() {
  forr(par, 0, 2) forr(bit, 0, cmplog) forr(pos, 0, tam) sp[par][bit][pos] =
      INF;
  forr(i, 0, 2) {
    forg(j, i, n, 2) { sp[i][0][j] = v[j]; }
    /*	<<"par "<<i<<endl;
            forr(j,0,n+3)
            {
                    <<sp[i][0][j]<<" ";
            }
            <<endl;*/
  }
  forr(par, 0, 2) {
    forr(bit, 1, cmplog) {
      forr(pos, 0, n) {
        sp[par][bit][pos] = min(sp[par][bit - 1][pos],
                                sp[par][bit - 1][pos + (1 << (bit - 1))]);
      }
      /*<<"par "<<par<<endl;
      forr(j,0,n+3)
      {
              <<sp[par][bit][j]<<" ";
      }
      <<endl;*/
    }
    //<<endl;
  }
  lstsparce[1] = 0;
  forr(i, 2, tam) lstsparce[i] = lstsparce[i / 2] + 1;
}
int getquery(int iz, int der) {
  int par = (iz % 2);
  int delta = (der - iz + 1);
  int bit = lstsparce[delta];
  return min(sp[par][bit][iz], sp[par][bit][der - (1 << bit) + 1]);
}
int vpos[tam];
void divide(ptr nodo, int iz, int der) {
  if (iz > der)
    return;
  //<<iz<<' '<<der<<endl;
  assert((der - iz + 1) % 2 == 0);

  if (der - iz + 1 == 2) {
    nodo->valor = {v[iz], v[der]};
    return;
  }
  int li = vpos[getquery(iz, der)];
  int ri = vpos[getquery(li + 1, der)];
  //<<li<<' '<<ri<<endl;
  nodo->valor = {v[li], v[ri]};

  nodo->iz = getnodo();
  nodo->iz->valor = {-1, -1};
  nodo->mid = getnodo();
  nodo->mid->valor = {-1, -1};
  nodo->der = getnodo();
  nodo->der->valor = {-1, -1};
  divide(nodo->iz, iz, li - 1);
  divide(nodo->mid, li + 1, ri - 1);
  divide(nodo->der, ri + 1, der);
}

int main() {

  forr(i, 0, tam) nodos[i].iz = nodos[i].der = nodos[i].mid = NULL;

  cin >> n;
  forr(i, 0, n) {
    cin >> v[i];
    vpos[v[i]] = i;
  }
  initsp();
  ptr root;
  priority_queue<iii, vector<iii>, greater<iii>> cola;

  root = getnodo();
  divide(root, 0, n - 1);
  // return 0;
  cola.push({root->valor, root});
  while (!cola.empty()) {
    auto par = cola.top();
    cola.pop();
    ptr cual = par.se;
    cout << par.fi.fi << ' ' << par.fi.se << ' ';
    if (cual->iz && cual->iz->valor.fi != -1)
      cola.push({cual->iz->valor, cual->iz});

    if (cual->mid && cual->mid->valor.fi != -1)
      cola.push({cual->mid->valor, cual->mid});

    if (cual->der && cual->der->valor.fi != -1)
      cola.push({cual->der->valor, cual->der});
  }
}