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

#include <array>
#include <iostream>
#include <limits>
#include <vector>

typedef int TYPE;
TYPE inf = -1;

using namespace std;

class Segment2d {
public:
  Segment2d();
  void set(const int y, const int x, const TYPE val);
  TYPE query(const int ys, const int ye, const int xs, const int xe);
  void init(const int h, const int w);
  void print();

private:
  TYPE query(const int ys, const int ye, const int xs, const int xe,
             const int qys, const int qye, const int qxs, const int qxe);
  TYPE queryY(const int ys, const int ye, const int qys, const int qye,
              const int qxs, const int qxe, const int k);
  TYPE queryX(const int xs, const int xe, const int qxs, const int qxe,
              const int ky, const int kx);
  TYPE _get(const int i, const int j);
  void _set(const int i, const int j, const TYPE val);
  int left(const int parent);
  int right(const int parent);
  int parent(const int child);
  TYPE eval(const TYPE t1, const TYPE t2);

  int height;
  int width;

  int height2;
  int width2;
  int logwidth;
  vector<TYPE> array;
};

void Segment2d::print() {
  for (int i = 0; i < 2 * height2 - 1; i++) {
    for (int j = 0; j < 2 * width2 - 1; j++) {
      cerr << _get(i, j) << " ";
    }
    cerr << endl;
  }
}

TYPE Segment2d::eval(const TYPE t1, const TYPE t2) {
  if (t1 == inf)
    return t2;
  else if (t2 == inf)
    return t1;
  else
    return min(t1, t2);
}

TYPE Segment2d::_get(const int i, const int j) {
  return array[(i << logwidth) + j];
}
void Segment2d::_set(const int i, const int j, const TYPE val) {
  array[(i << logwidth) + j] = val;
}

int Segment2d::left(const int parent) { return parent * 2 + 1; }

int Segment2d::right(const int parent) { return parent * 2 + 2; }

int Segment2d::parent(const int child) { return (child - 1) / 2; }

void Segment2d::init(const int h, const int w) {
  height = h;
  width = w;
  width2 = 1;
  logwidth = 0;
  while (width2 < width) {
    width2 *= 2;
    logwidth++;
  }
  logwidth++;

  height2 = 1;
  while (height2 < height)
    height2 *= 2;

  fill(array.begin(), array.end(), inf);
}

Segment2d::Segment2d() { array.resize(1 << 23); }

void Segment2d::set(int y, int x, TYPE val) {
  y += height2 - 1;
  x += width2 - 1;

  _set(y, x, val);

  vector<int> ys = {y};
  while (y > 0) {
    y = parent(y);
    ys.push_back(y);
  }
  vector<int> xs = {x};
  while (x > 0) {
    x = parent(x);
    xs.push_back(x);
  }

  for (int i = 1; i < ys.size(); i++) {
    const TYPE val = eval(_get(left(ys[i]), xs[0]), _get(right(ys[i]), xs[0]));
    _set(ys[i], xs[0], val);
  }

  for (int i = 0; i < ys.size(); i++) {
    for (int j = 1; j < xs.size(); j++) {
      const TYPE val =
          eval(_get(ys[i], left(xs[j])), _get(ys[i], right(xs[j])));
      _set(ys[i], xs[j], val);
    }
  }
}

TYPE Segment2d::query(const int qys, const int qye, const int qxs,
                      const int qxe) {
  return queryY(0, height2, qys, qye, qxs, qxe, 0);
}

TYPE Segment2d::queryY(const int ys, const int ye, const int qys, const int qye,
                       const int qxs, const int qxe, const int k) {
  if (qye <= ys || ye <= qys) {
    return inf;
  } else if (qys <= ys && ye <= qye) {
    return queryX(0, width2, qxs, qxe, k, 0);
  } else {
    const int mid_y = (ys + ye) / 2;
    return eval(queryY(ys, mid_y, qys, qye, qxs, qxe, left(k)),
                queryY(mid_y, ye, qys, qye, qxs, qxe, right(k)));
  }
}

TYPE Segment2d::queryX(const int xs, const int xe, const int qxs, const int qxe,
                       const int ky, const int kx) {
  if (qxe <= xs || xe <= qxs) {
    return inf;
  } else if (qxs <= xs && xe <= qxe) {
    return _get(ky, kx);
  } else {
    const int mid_x = (xs + xe) / 2;
    return eval(queryX(xs, mid_x, qxs, qxe, ky, left(kx)),
                queryX(mid_x, xe, qxs, qxe, ky, right(kx)));
  }
}

void test() {
  const int height = 3;
  const int width = 3;
  Segment2d seg;
  seg.init(height, width);

  for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
      seg.set(i, j, i * 100 + j);
    }
  }
  seg.print();

  for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
      cerr << seg.query(i, i + 1, j, j + 1) << " ";
    }
    cerr << endl;
  }
}

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

  Segment2d seg;

  while (true) {
    int r, c, q;
    cin >> r >> c >> q;
    if (r == 0 && c == 0 && q == 0)
      break;

    seg.init(r, c);

    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        TYPE v;
        cin >> v;
        seg.set(i, j, v);
      }
    }

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

Error: MLE

Fixed submission:

#include <array>
#include <iostream>
#include <limits>
#include <vector>

typedef long long TYPE;
TYPE inf = 10000000000000000;

using namespace std;

class Segment2d {
public:
  Segment2d();
  void set(const int y, const int x, const TYPE val);
  TYPE query(const int ys, const int ye, const int xs, const int xe);
  void init(const int h, const int w);
  void print();

private:
  TYPE query(const int ys, const int ye, const int xs, const int xe,
             const int qys, const int qye, const int qxs, const int qxe);
  TYPE queryY(const int ys, const int ye, const int qys, const int qye,
              const int qxs, const int qxe, const int k);
  TYPE queryX(const int xs, const int xe, const int qxs, const int qxe,
              const int ky, const int kx);
  TYPE _get(const int i, const int j);
  void _set(const int i, const int j, const TYPE val);
  int left(const int parent);
  int right(const int parent);
  int parent(const int child);

  int height;
  int width;

  int height2;
  int width2;
  int logwidth;
  vector<TYPE> array;
};

void Segment2d::print() {
  for (int i = 0; i < 2 * height2 - 1; i++) {
    for (int j = 0; j < 2 * width2 - 1; j++) {
      cerr << _get(i, j) << " ";
    }
    cerr << endl;
  }
}

TYPE Segment2d::_get(const int i, const int j) {
  return array[(i << logwidth) + j];
}
void Segment2d::_set(const int i, const int j, const TYPE val) {
  array[(i << logwidth) + j] = val;
}

int Segment2d::left(const int parent) { return parent * 2 + 1; }

int Segment2d::right(const int parent) { return parent * 2 + 2; }

int Segment2d::parent(const int child) { return (child - 1) / 2; }

void Segment2d::init(const int h, const int w) {
  height = h;
  width = w;
  width2 = 1;
  logwidth = 0;
  while (width2 < width) {
    width2 *= 2;
    logwidth++;
  }
  logwidth++;

  height2 = 1;
  while (height2 < height)
    height2 *= 2;

  fill(array.begin(), array.end(), inf);
}

Segment2d::Segment2d() { array.resize(1 << 23); }

void Segment2d::set(int y, int x, TYPE val) {
  y += height2 - 1;
  x += width2 - 1;

  _set(y, x, val);

  vector<int> ys = {y};
  while (y > 0) {
    y = parent(y);
    ys.push_back(y);
  }
  vector<int> xs = {x};
  while (x > 0) {
    x = parent(x);
    xs.push_back(x);
  }

  for (int i = 1; i < ys.size(); i++) {
    const TYPE val = min(_get(left(ys[i]), xs[0]), _get(right(ys[i]), xs[0]));
    _set(ys[i], xs[0], val);
  }

  for (int i = 0; i < ys.size(); i++) {
    for (int j = 1; j < xs.size(); j++) {
      const TYPE val = min(_get(ys[i], left(xs[j])), _get(ys[i], right(xs[j])));
      _set(ys[i], xs[j], val);
    }
  }
}

TYPE Segment2d::query(const int qys, const int qye, const int qxs,
                      const int qxe) {
  return queryY(0, height2, qys, qye, qxs, qxe, 0);
}

TYPE Segment2d::queryY(const int ys, const int ye, const int qys, const int qye,
                       const int qxs, const int qxe, const int k) {
  if (qye <= ys || ye <= qys) {
    return inf;
  } else if (qys <= ys && ye <= qye) {
    return queryX(0, width2, qxs, qxe, k, 0);
  } else {
    const int mid_y = (ys + ye) / 2;
    return min(queryY(ys, mid_y, qys, qye, qxs, qxe, left(k)),
               queryY(mid_y, ye, qys, qye, qxs, qxe, right(k)));
  }
}

TYPE Segment2d::queryX(const int xs, const int xe, const int qxs, const int qxe,
                       const int ky, const int kx) {
  if (qxe <= xs || xe <= qxs) {
    return inf;
  } else if (qxs <= xs && xe <= qxe) {
    return _get(ky, kx);
  } else {
    const int mid_x = (xs + xe) / 2;
    return min(queryX(xs, mid_x, qxs, qxe, ky, left(kx)),
               queryX(mid_x, xe, qxs, qxe, ky, right(kx)));
  }
}

void test() {
  const int height = 3;
  const int width = 3;
  Segment2d seg;
  seg.init(height, width);

  for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
      seg.set(i, j, i * 100 + j);
    }
  }
  seg.print();

  for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
      cerr << seg.query(i, i + 1, j, j + 1) << " ";
    }
    cerr << endl;
  }
}

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

  Segment2d seg;

  while (true) {
    int r, c, q;
    cin >> r >> c >> q;
    if (r == 0 && c == 0 && q == 0)
      break;

    seg.init(r, c);

    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        TYPE v;
        cin >> v;
        seg.set(i, j, v);
      }
    }

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