Problem p03950 (C++)

Buggy submission (status: Time Limit Exceeded):
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
// #pragma GCC optimize("O3")
#include <bits/stdc++.h>

using namespace std;
typedef long double ld;
typedef long long ll;
int w, h;
const int maxN = 3 * (int)1e5 + 10;
int x[maxN], y[maxN];
int n;
int best = -1488;
int nx[maxN], ny[maxN];
int L[maxN], R[maxN];
int t[2][4 * maxN];

void upd(int tp, int v, int tl, int tr, int pos, int val) {
  if (tl == tr) {
    t[tp][v] = max(t[tp][v], val);
    return;
  }
  int tm = (tl + tr) / 2;
  if (pos <= tm)
    upd(tp, v + v, tl, tm, pos, val);
  else
    upd(tp, v + v + 1, tm + 1, tr, pos, val);
  t[tp][v] = max(t[tp][2 * v], t[tp][2 * v + 1]);
}

const int INF = (int)1e9;

int get(int tp, int v, int tl, int tr, int l, int r) {
  if (l > r)
    return -INF;
  if (tl == l && tr == r)
    return t[tp][v];
  int tm = (tl + tr) / 2;
  return max(get(tp, 2 * v, tl, tm, l, min(r, tm)),
             get(tp, 2 * v + 1, tm + 1, tr, max(tm + 1, l), r));
}

int fenw[2][maxN];
int N;
void updMax(int tp, int v, int by) {
  while (v <= N) {
    fenw[tp][v] = max(fenw[tp][v], by);
    v = (v | (v - 1)) + 1;
  }
}
int getMax(int tp, int v) {
  int ans = -INF;
  while (v > 0) {
    ans = max(ans, fenw[tp][v]);
    v &= (v - 1);
  }
  return ans;
}

int idY[maxN];

int lst_fenw[maxN];
int SZ;
int QQ;
const int P = 1e7;
int evs[P];
void upd(int v, int by) {
  while (v <= SZ) {
    lst_fenw[v] = max(lst_fenw[v], by);
    evs[QQ++] = v;
    v = (v | (v - 1)) + 1;
  }
}

int get(int v) {
  int ans = -INF;
  while (v > 0) {
    ans = max(ans, lst_fenw[v]);
    v &= (v - 1);
  }
  return ans;
}

void redo() {
  for (int i = 0; i <= QQ; i++) {
    lst_fenw[evs[i]] = -INF;
  }
  QQ = 0;
}

const int BUBEN = 15;
int RR[BUBEN + 2][BUBEN + 2];
int LL[BUBEN + 2][BUBEN + 2];
void solve(int l, int r) {
  if (l == r) {
    best = max(best, h);
    best = max(best, w);
    return;
  }
  if (r - l <= BUBEN) {
    for (int a = l; a <= r; a++) {
      int at_least = h;
      int at_most = 0;
      for (int b = a + 1; b <= r; b++) {
        RR[a - l][b - l] = at_least;
        LL[a - l][b - l] = at_most;
        if (y[b] >= y[a])
          at_least = min(at_least, y[b]);
        if (y[b] <= y[a])
          at_most = max(at_most, y[b]);
      }
    }
    for (int a = l; a <= r; a++) {
      int at_least = h;
      int at_most = 0;
      for (int b = a - 1; b >= l; b--) {
        best = max(best, min(at_least, RR[b - l][a - l]) -
                             max(at_most, LL[b - l][a - l]) + x[a] - x[b]);
        if (y[b] >= y[a])
          at_least = min(at_least, y[b]);
        if (y[b] <= y[a])
          at_most = max(at_most, y[b]);
      }
    }
    return;
  }
  int mid = (l + r) / 2;
  solve(l, mid);
  solve(mid + 1, r);
  upd(1, 0);
  for (int i = mid; i >= l; i--) {
    L[i] = get(idY[i]);
    upd(idY[i], y[i]);
  }
  redo();
  upd(1, -h);
  for (int i = mid; i >= l; i--) {
    R[i] = -get(SZ + 1 - idY[i]);
    upd(SZ + 1 - idY[i], -y[i]);
  }
  redo();
  upd(1, 0);
  for (int i = mid + 1; i <= r; i++) {
    L[i] = get(idY[i]);
    upd(idY[i], y[i]);
  }
  redo();
  upd(1, -h);
  for (int i = mid + 1; i <= r; i++) {
    R[i] = -get(SZ + 1 - idY[i]);
    upd(SZ + 1 - idY[i], -y[i]);
  }
  redo();
  vector<int> allL;
  for (int i = l; i <= r; i++) {
    allL.emplace_back(L[i]);
  }
  sort(allL.begin(), allL.end());
  allL.erase(unique(allL.begin(), allL.end()), allL.end());
  vector<pair<int, int>> events;
  for (int i = l; i <= r; i++) {
    events.emplace_back(R[i], i);
  }
  sort(events.begin(), events.end());
  int sz = allL.size();
  int n = sz;
  N = n;
  for (int i = 1; i <= sz; i++) {
    for (int j = 0; j < 2; j++) {
      fenw[j][i] = -INF;
    }
  }
  for (auto it : events) {
    int he =
        lower_bound(allL.begin(), allL.end(), L[it.second]) - allL.begin() + 1;
    if (it.second <= mid) {
      updMax(0, N + 1 - he, it.first - L[it.second] - x[it.second]);
      updMax(1, he, it.first - x[it.second]);
    } else {
      best = max(best, x[it.second] + getMax(0, N + 1 - he));
      best = max(best, x[it.second] - L[it.second] + getMax(1, he));
    }
  }
  for (int i = 1; i <= 4 * sz; i++) {
    for (int j = 0; j < 2; j++) {
      fenw[j][i] = -INF;
    }
  }
  reverse(events.begin(), events.end());
  for (auto it : events) {
    int he =
        lower_bound(allL.begin(), allL.end(), L[it.second]) - allL.begin() + 1;
    if (it.second <= mid) {
      updMax(0, N + 1 - he, -L[it.second] - x[it.second]);
      updMax(1, he, -x[it.second]);
    } else {
      best = max(best, it.first + x[it.second] + getMax(0, N + 1 - he));
      best = max(best, it.first + x[it.second] - L[it.second] + getMax(1, he));
    }
  }
}

mt19937 rnd(3535);
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  //    freopen("input.txt", "r", stdin);
  cin >> w >> h >> n;
  for (int a : {0, w}) {
    for (int b : {0, h}) {
      n++;
      x[n] = a;
      y[n] = b;
    }
  }
  vector<int> allx, ally;
  vector<int> pts;
  for (int i = 1; i <= n; i++) {
    cin >> x[i] >> y[i];
    pts.emplace_back(i);
  }
  for (int step = 0; step < 2; step++) {
    sort(pts.begin(), pts.end(), [&](int a, int b) { return x[a] < x[b]; });
    for (int i = 0; i < pts.size(); i++) {
      nx[i + 1] = x[pts[i]];
      ny[i + 1] = y[pts[i]];
    }
    vector<int> gg;
    for (int i = 1; i <= n; i++) {
      x[i] = nx[i];
      y[i] = ny[i];
      gg.emplace_back(y[i]);
    }
    sort(gg.begin(), gg.end());
    for (int i = 1; i <= n; i++) {
      idY[i] = lower_bound(gg.begin(), gg.end(), y[i]) - gg.begin() + 1;
    }
    SZ = gg.size();
    if (step <= 1) {
      solve(1, n);
    } else {
      for (int i = 1; i <= n; i++) {
        solve(i, min(i + 2, n));
      }
    }
    swap(w, h);
    for (int i = 1; i <= n; i++) {
      swap(x[i], y[i]);
    }
  }
  cout << 2 * best;
  return 0;
}


Fixed submission:
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
// #pragma GCC optimize("O3")
#include <bits/stdc++.h>

using namespace std;
typedef long double ld;
typedef long long ll;
int w, h;
const int maxN = 3 * (int)1e5 + 10;
int x[maxN], y[maxN];
int n;
int best = -1488;
int nx[maxN], ny[maxN];
int L[maxN], R[maxN];
int t[2][4 * maxN];

void upd(int tp, int v, int tl, int tr, int pos, int val) {
  if (tl == tr) {
    t[tp][v] = max(t[tp][v], val);
    return;
  }
  int tm = (tl + tr) / 2;
  if (pos <= tm)
    upd(tp, v + v, tl, tm, pos, val);
  else
    upd(tp, v + v + 1, tm + 1, tr, pos, val);
  t[tp][v] = max(t[tp][2 * v], t[tp][2 * v + 1]);
}

const int INF = (int)1e9;

int get(int tp, int v, int tl, int tr, int l, int r) {
  if (l > r)
    return -INF;
  if (tl == l && tr == r)
    return t[tp][v];
  int tm = (tl + tr) / 2;
  return max(get(tp, 2 * v, tl, tm, l, min(r, tm)),
             get(tp, 2 * v + 1, tm + 1, tr, max(tm + 1, l), r));
}

int fenw[2][maxN];
int N;
void updMax(int tp, int v, int by) {
  while (v <= N) {
    fenw[tp][v] = max(fenw[tp][v], by);
    v = (v | (v - 1)) + 1;
  }
}
int getMax(int tp, int v) {
  int ans = -INF;
  while (v > 0) {
    ans = max(ans, fenw[tp][v]);
    v &= (v - 1);
  }
  return ans;
}

int idY[maxN];

int lst_fenw[maxN];
int SZ;
int QQ;
const int P = 1e7;
int evs[P];
void upd(int v, int by) {
  while (v <= SZ) {
    lst_fenw[v] = max(lst_fenw[v], by);
    evs[QQ++] = v;
    v = (v | (v - 1)) + 1;
  }
}

int get(int v) {
  int ans = -INF;
  while (v > 0) {
    ans = max(ans, lst_fenw[v]);
    v &= (v - 1);
  }
  return ans;
}

void redo() {
  for (int i = 0; i <= QQ; i++) {
    lst_fenw[evs[i]] = -INF;
  }
  QQ = 0;
}

const int BUBEN = 20;
int RR[BUBEN + 2][BUBEN + 2];
int LL[BUBEN + 2][BUBEN + 2];
void solve(int l, int r) {
  if (l == r) {
    best = max(best, h);
    best = max(best, w);
    return;
  }
  if (r - l <= BUBEN) {
    for (int a = l; a <= r; a++) {
      int at_least = h;
      int at_most = 0;
      for (int b = a + 1; b <= r; b++) {
        RR[a - l][b - l] = at_least;
        LL[a - l][b - l] = at_most;
        if (y[b] >= y[a])
          at_least = min(at_least, y[b]);
        if (y[b] <= y[a])
          at_most = max(at_most, y[b]);
      }
    }
    for (int a = l; a <= r; a++) {
      int at_least = h;
      int at_most = 0;
      for (int b = a - 1; b >= l; b--) {
        best = max(best, min(at_least, RR[b - l][a - l]) -
                             max(at_most, LL[b - l][a - l]) + x[a] - x[b]);
        if (y[b] >= y[a])
          at_least = min(at_least, y[b]);
        if (y[b] <= y[a])
          at_most = max(at_most, y[b]);
      }
    }
    return;
  }
  int mid = (l + r) / 2;
  solve(l, mid);
  solve(mid + 1, r);
  upd(1, 0);
  for (int i = mid; i >= l; i--) {
    L[i] = get(idY[i]);
    upd(idY[i], y[i]);
  }
  redo();
  upd(1, -h);
  for (int i = mid; i >= l; i--) {
    R[i] = -get(SZ + 1 - idY[i]);
    upd(SZ + 1 - idY[i], -y[i]);
  }
  redo();
  upd(1, 0);
  for (int i = mid + 1; i <= r; i++) {
    L[i] = get(idY[i]);
    upd(idY[i], y[i]);
  }
  redo();
  upd(1, -h);
  for (int i = mid + 1; i <= r; i++) {
    R[i] = -get(SZ + 1 - idY[i]);
    upd(SZ + 1 - idY[i], -y[i]);
  }
  redo();
  vector<int> allL;
  for (int i = l; i <= r; i++) {
    allL.emplace_back(L[i]);
  }
  sort(allL.begin(), allL.end());
  allL.erase(unique(allL.begin(), allL.end()), allL.end());
  vector<pair<int, int>> events;
  for (int i = l; i <= r; i++) {
    events.emplace_back(R[i], i);
  }
  sort(events.begin(), events.end());
  int sz = allL.size();
  int n = sz;
  N = n;
  for (int i = 1; i <= sz; i++) {
    for (int j = 0; j < 2; j++) {
      fenw[j][i] = -INF;
    }
  }
  for (auto it : events) {
    int he =
        lower_bound(allL.begin(), allL.end(), L[it.second]) - allL.begin() + 1;
    if (it.second <= mid) {
      updMax(0, N + 1 - he, it.first - L[it.second] - x[it.second]);
      updMax(1, he, it.first - x[it.second]);
    } else {
      best = max(best, x[it.second] + getMax(0, N + 1 - he));
      best = max(best, x[it.second] - L[it.second] + getMax(1, he));
    }
  }
  for (int i = 1; i <= 4 * sz; i++) {
    for (int j = 0; j < 2; j++) {
      fenw[j][i] = -INF;
    }
  }
  reverse(events.begin(), events.end());
  for (auto it : events) {
    int he =
        lower_bound(allL.begin(), allL.end(), L[it.second]) - allL.begin() + 1;
    if (it.second <= mid) {
      updMax(0, N + 1 - he, -L[it.second] - x[it.second]);
      updMax(1, he, -x[it.second]);
    } else {
      best = max(best, it.first + x[it.second] + getMax(0, N + 1 - he));
      best = max(best, it.first + x[it.second] - L[it.second] + getMax(1, he));
    }
  }
}

mt19937 rnd(3535);
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  //    freopen("input.txt", "r", stdin);
  cin >> w >> h >> n;
  for (int a : {0, w}) {
    for (int b : {0, h}) {
      n++;
      x[n] = a;
      y[n] = b;
    }
  }
  vector<int> allx, ally;
  vector<int> pts;
  for (int i = 1; i <= n; i++) {
    cin >> x[i] >> y[i];
    pts.emplace_back(i);
  }
  for (int step = 0; step < 2; step++) {
    sort(pts.begin(), pts.end(), [&](int a, int b) { return x[a] < x[b]; });
    for (int i = 0; i < pts.size(); i++) {
      nx[i + 1] = x[pts[i]];
      ny[i + 1] = y[pts[i]];
    }
    vector<int> gg;
    for (int i = 1; i <= n; i++) {
      x[i] = nx[i];
      y[i] = ny[i];
      gg.emplace_back(y[i]);
    }
    sort(gg.begin(), gg.end());
    for (int i = 1; i <= n; i++) {
      idY[i] = lower_bound(gg.begin(), gg.end(), y[i]) - gg.begin() + 1;
    }
    SZ = gg.size();
    if (step <= 1) {
      solve(1, n);
    } else {
      for (int i = 1; i <= n; i++) {
        solve(i, min(i + 2, n));
      }
    }
    swap(w, h);
    for (int i = 1; i <= n; i++) {
      swap(x[i], y[i]);
    }
  }
  cout << 2 * best;
  return 0;
}