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

#include <bits/stdc++.h>
using namespace std;
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
#define DEBUG(x) cerr << #x << " = " << x << endl
constexpr int INF = INT_MAX;
int H, W, Q;
struct Row {
  int N;
  vector<int> data;
  Row() {
    N = 1;
    while (N < W)
      N *= 2;
    data.assign(2 * N - 1, INF);
  }
  int get(int x) { return data[x + N - 1]; }
  void update(int k, int a) {
    k += N - 1;
    data[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      data[k] = min(data[2 * k + 1], data[2 * k + 2]);
    }
  }
  int query(int a, int b) { return query2(a, b, 0, 0, N); }
  int query2(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return INF;
    if (a <= l && r <= b)
      return data[k];

    return min(query2(a, b, 2 * k + 1, l, (l + r) / 2),
               query2(a, b, 2 * k + 2, (l + r) / 2, r));
  }
  void clear() { data.clear(); }
};
struct Grid {
  int K;
  int SQRT_N;
  vector<Row> data;
  vector<Row> stat;
  Grid() {
    SQRT_N = 0;
    while (SQRT_N * SQRT_N < H)
      SQRT_N++;
    K = (H + SQRT_N - 1) / SQRT_N;
    data.assign(SQRT_N * K, Row());
    stat.assign(K, Row());
  }
  void update(const int y, const int x, const int value) {
    data[y].update(x, value);
    const int k = y / SQRT_N;
    stat[k].update(x, min(stat[k].get(x), data[y].get(x)));
  }
  int query(const int y1, const int x1, const int y2, const int x2) {
    int ret = INF;
    for (int k = 0; k < K; ++k) {
      int l = k * SQRT_N, r = (k + 1) * SQRT_N;
      if (r <= y1 || y2 <= l)
        continue;
      if (y1 <= l && r <= y2) {
        ret = min(ret, stat[k].query(x1, x2));
      } else {
        for (int i = max(y1, l); i < min(y2, r); ++i) {
          ret = min(ret, data[i].query(x1, x2));
        }
      }
    }
    return ret;
  }
};
signed main() {
  ios::sync_with_stdio(false);
  while (true) {
    cin >> H >> W >> Q;
    if (H == 0 && W == 0 && Q == 0)
      break;
    bool doswap = false;
    if (H > W) {
      doswap = true;
      swap(H, W);
    }
    Grid g;
    if (doswap) {
      REP(y, W) REP(x, H) {
        int v;
        cin >> v;
        g.update(x, y, v);
      }
    } else {
      REP(y, H) REP(x, W) {
        int v;
        cin >> v;
        g.update(y, x, v);
      }
    }
    REP(q, Q) {
      int y1, x1, y2, x2;
      cin >> y1 >> x1 >> y2 >> x2;
      if (doswap) {
        swap(x1, y1);
        swap(x2, y2);
      }
      cout << g.query(y1, x1, y2 + 1, x2 + 1) << endl;
    }
  }
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
#define DEBUG(x) cerr << #x << " = " << x << endl
constexpr int SQRT_N = 50;
constexpr int INF = INT_MAX;
int H, W, Q;
struct Row {
  int N;
  vector<int> data;
  Row() {
    N = 1;
    while (N < W)
      N *= 2;
    data.assign(2 * N - 1, INF);
  }
  int get(int x) { return data[x + N - 1]; }
  void update(int k, int a) {
    k += N - 1;
    data[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      data[k] = min(data[2 * k + 1], data[2 * k + 2]);
    }
  }
  int query(int a, int b) { return query2(a, b, 0, 0, N); }
  int query2(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return INF;
    if (a <= l && r <= b)
      return data[k];

    return min(query2(a, b, 2 * k + 1, l, (l + r) / 2),
               query2(a, b, 2 * k + 2, (l + r) / 2, r));
  }
  void clear() { data.clear(); }
};
struct Grid {
  int K;
  vector<Row> data;
  vector<Row> stat;
  Grid() {
    K = (H + SQRT_N - 1) / SQRT_N;
    data.assign(SQRT_N * K, Row());
    stat.assign(K, Row());
  }
  void update(const int y, const int x, const int value) {
    data[y].update(x, value);
    const int k = y / SQRT_N;
    stat[k].update(x, min(stat[k].get(x), data[y].get(x)));
  }
  int query(const int y1, const int x1, const int y2, const int x2) {
    int ret = INF;
    for (int k = 0; k < K; ++k) {
      int l = k * SQRT_N, r = (k + 1) * SQRT_N;
      if (r <= y1 || y2 <= l)
        continue;
      if (y1 <= l && r <= y2) {
        ret = min(ret, stat[k].query(x1, x2));
      } else {
        for (int i = max(y1, l); i < min(y2, r); ++i) {
          ret = min(ret, data[i].query(x1, x2));
        }
      }
    }
    return ret;
  }
};
signed main() {
  ios::sync_with_stdio(false);
  while (true) {
    cin >> H >> W >> Q;
    if (H == 0 && W == 0 && Q == 0)
      break;
    bool doswap = false;
    if (H > W) {
      doswap = true;
      swap(H, W);
    }
    Grid g;
    if (doswap) {
      REP(y, W) REP(x, H) {
        int v;
        cin >> v;
        g.update(x, y, v);
      }
    } else {
      REP(y, H) REP(x, W) {
        int v;
        cin >> v;
        g.update(y, x, v);
      }
    }
    REP(q, Q) {
      int y1, x1, y2, x2;
      cin >> y1 >> x1 >> y2 >> x2;
      if (doswap) {
        swap(x1, y1);
        swap(x2, y2);
      }
      cout << g.query(y1, x1, y2 + 1, x2 + 1) << endl;
    }
  }
}