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

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

const int maxn = 1e6 + 5;

int tree[16 * maxn], n, m, f[maxn], q;
int r1, r2, c1, c2;

void ini0(int pos1, int pos2, int begin, int end, int r) {
  if (begin == end)
    tree[pos1 * m * 4 + pos2] = f[r * m + begin];
  else {
    int mid = (begin + end) >> 1;
    ini0(pos1, pos2 << 1, begin, mid, r);
    ini0(pos1, (pos2 << 1) | 1, mid + 1, end, r);
    if (tree[pos1 * m * 4 + (pos2 << 1)] <
        tree[pos1 * m * 4 + ((pos2 << 1) | 1)])
      tree[pos1 * m * 4 + pos2] = tree[pos1 * m * 4 + (pos2 << 1)];
    else
      tree[pos1 * m * 4 + pos2] = tree[pos1 * m * 4 + ((pos2 << 1) | 1)];
  }
}

void ini1(int pos1, int pos2, int begin, int end) {
  if (tree[(pos1 << 1) * m * 4 + pos2] < tree[((pos1 << 1) | 1) * m * 4 + pos2])
    tree[pos1 * m * 4 + pos2] = tree[(pos1 << 1) * m * 4 + pos2];
  else
    tree[pos1 * m * 4 + pos2] = tree[((pos1 << 1) | 1) * m * 4 + pos2];
  if (begin != end) {
    int mid = (begin + end) >> 1;
    ini1(pos1, pos2 << 1, begin, mid);
    ini1(pos1, (pos2 << 1) | 1, mid + 1, end);
  }
}

void ini(int pos, int begin, int end) {
  if (begin == end)
    ini0(pos, 1, 0, m - 1, begin);
  else {
    int mid = (begin + end) >> 1;
    ini(pos << 1, begin, mid);
    ini((pos << 1) | 1, mid + 1, end);
    ini1(pos, 1, 0, m - 1);
  }
}

int find2(int pos1, int pos2, int begin, int end) {
  if (c1 <= begin && end <= c2)
    return tree[pos1 * 4 * m + pos2];
  else {
    int mid = (begin + end) >> 1;
    if (c2 <= mid)
      return find2(pos1, pos2 << 1, begin, mid);
    else if (c1 > mid)
      return find2(pos1, (pos2 << 1) | 1, mid + 1, end);
    else
      return min(find2(pos1, pos2 << 1, begin, mid),
                 find2(pos1, (pos2 << 1) | 1, mid + 1, end));
  }
}

int find(int pos, int begin, int end) {
  if (r1 <= begin && end <= r2)
    return find2(pos, 1, 0, m - 1);
  else {
    int mid = (begin + end) >> 1;
    if (r2 <= mid)
      return find(pos << 1, begin, mid);
    else if (r1 > mid)
      return find((pos << 1) | 1, mid + 1, end);
    else
      return min(find(pos << 1, begin, mid),
                 find((pos << 1) | 1, mid + 1, end));
  }
}

int main() {
  while (scanf("%d%d%d", &n, &m, &q) == 3 && (n || m || q)) {
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++)
        scanf("%d", &f[i * m + j]);
    ini(1, 0, n - 1);
    for (int i = 0; i < q; i++) {
      scanf("%d%d%d%d", &r1, &c1, &r2, &c2);
      printf("%d\\n", find(1, 0, n - 1));
    }
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;

int tree[16500000];

void build(int x, int y, int num, int lx, int rx, int ly, int ry, int pos) {
  if (lx == rx && ly == ry) {
    tree[pos] = num;
    return;
  }
  int midx = (lx + rx) / 2, midy = (ly + ry) / 2;
  if (x <= midx && y <= midy) {
    build(x, y, num, lx, midx, ly, midy, pos * 4);
    if (tree[pos] == -1 || tree[pos * 4] < tree[pos])
      tree[pos] = tree[pos * 4];
  }
  if (x <= midx && y > midy) {
    build(x, y, num, lx, midx, midy + 1, ry, pos * 4 + 1);
    if (tree[pos] == -1 || tree[pos * 4 + 1] < tree[pos])
      tree[pos] = tree[pos * 4 + 1];
  }
  if (x > midx && y <= midy) {
    build(x, y, num, midx + 1, rx, ly, midy, pos * 4 + 2);
    if (tree[pos] == -1 || tree[pos * 4 + 2] < tree[pos])
      tree[pos] = tree[pos * 4 + 2];
  }
  if (x > midx && y > midy) {
    build(x, y, num, midx + 1, rx, midy + 1, ry, pos * 4 + 3);
    if (tree[pos] == -1 || tree[pos * 4 + 3] < tree[pos])
      tree[pos] = tree[pos * 4 + 3];
  }
  //   printf("%d %d %d %d %d\\n",lx,rx,ly,ry,tree[pos]);
  return;
}

int query(int x, int y, int xx, int yy, int lx, int rx, int ly, int ry,
          int pos) {
  // printf("%d %d %d %d %d %d %d %d\\n",x,y,xx,yy,lx,rx,ly,ry);
  if (x <= lx && xx >= rx && y <= ly && yy >= ry)
    return tree[pos];
  if (lx == rx && ly == ry)
    return tree[pos];
  int midx = (lx + rx) / 2, midy = (ly + ry) / 2;
  int now = -1, temp;
  if (x <= midx && y <= midy) {
    temp = query(x, y, xx, yy, lx, midx, ly, midy, pos * 4);
    if (now == -1 || temp < now)
      now = temp;
  }
  if (x <= midx && yy > midy) {
    temp = query(x, y, xx, yy, lx, midx, midy + 1, ry, pos * 4 + 1);
    if (now == -1 || temp < now)
      now = temp;
  }
  if (xx > midx && y <= midy) {
    temp = query(x, y, xx, yy, midx + 1, rx, ly, midy, pos * 4 + 2);
    if (now == -1 || temp < now)
      now = temp;
  }
  if (xx > midx && yy > midy) {
    temp = query(x, y, xx, yy, midx + 1, rx, midy + 1, ry, pos * 4 + 3);
    if (now == -1 || temp < now)
      now = temp;
  }
  return now;
}

int main() {
  int n, m, q, i, j, x, y, xx, yy;
  while (scanf("%d%d%d", &n, &m, &q) == 3) {
    if (!n && !m && !q)
      break;
    memset(tree, -1, sizeof(tree));
    for (i = 1; i <= n; i++)
      for (j = 1; j <= m; j++) {
        scanf("%d", &x);
        build(i, j, x, 1, n, 1, m, 1);
      }
    while (q--) {
      scanf("%d%d%d%d", &x, &y, &xx, &yy);
      printf("%d\\n", query(x + 1, y + 1, xx + 1, yy + 1, 1, n, 1, m, 1));
    }
  }
  return 0;
}