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

#include <algorithm>
#include <climits>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;

template <class T> inline void chmin(T &a, const T &b) {
  if (b < a)
    a = b;
}

typedef int type;
const type INIT = INT_MAX;

class segment_tree {
private:
  int n;
  vector<type> dat;

  inline type function(type a, type b) const { return min(a, b); }

  type query(int a, int b, int k, int l, int r) const {
    if (r <= a || b <= l)
      return INIT;

    if (a <= l && r <= b) {
      return dat[k];
    } else {
      const type vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      const type vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return function(vl, vr);
    }
  }

public:
  segment_tree(int n_) {
    n = 1;
    while (n < n_)
      n *= 2;
    dat.resize(2 * n - 1, INIT);
  }

  inline void update(int k, type a) {
    k += n - 1;
    dat[k] = a;

    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = function(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }

  inline type query(int a, int b) const { return query(a, b, 0, 0, n); }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  for (int r, c, q; cin >> r >> c >> q, r;) {
    bool is_row = (r <= c);
    vector<segment_tree> seg(min(r, c), segment_tree(max(r, c)));

    for (int i = 0; i < r; ++i) {
      for (int j = 0; j < c; ++j) {
        type in;
        cin >> in;

        if (is_row)
          seg[i].update(j, in);
        else
          seg[j].update(i, in);
      }
    }

    for (int i = 0; i < q; ++i) {
      int start, end, a, b;
      if (is_row)
        cin >> start >> a >> end >> b;
      else
        cin >> a >> start >> b >> end;
      ++b;

      type ans = INIT;
      for (int j = start; j <= end; ++j) {
        chmin(ans, seg[j].query(a, b));
      }

      cout << ans << endl;
    }
  }

  return EXIT_SUCCESS;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;

typedef int type;
const type INIT = INT_MAX;

class segment_tree {
private:
  int n;
  vector<type> dat;

  inline type function(type a, type b) const { return min(a, b); }

  type query(int a, int b, int k, int l, int r) const {
    if (r <= a || b <= l)
      return INIT;

    if (a <= l && r <= b) {
      return dat[k];
    } else {
      const type vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      const type vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return function(vl, vr);
    }
  }

public:
  segment_tree(int n_) {
    n = 1;
    while (n < n_)
      n *= 2;
    dat.resize(2 * n - 1, INIT);
  }

  inline void update(int k, type a) {
    k += n - 1;
    dat[k] = a;

    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = function(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }

  inline type query(int a, int b) const { return query(a, b, 0, 0, n); }

  const vector<type> &data() const { return dat; }

  void merge(const segment_tree &s) {
    const vector<type> &tmp = s.data();
    if (dat.size() != tmp.size())
      return;
    for (int i = 0; i < (int)dat.size(); ++i) {
      dat[i] = function(dat[i], tmp[i]);
    }
  }
};

class segment_tree_2d {
private:
  int n;
  vector<segment_tree> dat;

  inline type function(type a, type b) const { return min(a, b); }

  type query(int r1, int r2, int c1, int c2, int k, int l, int r) const {
    if (r <= r1 || r2 <= l)
      return INIT;

    if (r1 <= l && r <= r2) {
      return dat[k].query(c1, c2);
    } else {
      const type vl = query(r1, r2, c1, c2, k * 2 + 1, l, (l + r) / 2);
      const type vr = query(r1, r2, c1, c2, k * 2 + 2, (l + r) / 2, r);
      return function(vl, vr);
    }
  }

public:
  segment_tree_2d(int r, int c) {
    n = 1;
    while (n < r)
      n *= 2;
    dat.resize(2 * n - 1, segment_tree(c));
  }

  inline void update(int y, int x, type a) {
    y += n - 1;
    dat[y].update(x, a);
  }

  inline void revise() {
    for (int i = n - 2; i >= 0; --i) {
      dat[i].merge(dat[i * 2 + 1]);
      dat[i].merge(dat[i * 2 + 2]);
    }
  }

  inline type query(int r1, int r2, int c1, int c2) const {
    return query(r1, r2, c1, c2, 0, 0, n);
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  for (int r, c, q; cin >> r >> c >> q, r;) {
    segment_tree_2d seg(r, c);
    for (int i = 0; i < r; ++i) {
      for (int j = 0; j < c; ++j) {
        int in;
        cin >> in;
        seg.update(i, j, in);
      }
    }
    seg.revise();

    for (int i = 0; i < q; ++i) {
      int r1, r2, c1, c2;
      cin >> r1 >> c1 >> r2 >> c2;
      cout << seg.query(r1, r2 + 1, c1, c2 + 1) << endl;
    }
  }

  return EXIT_SUCCESS;
}