Cod sursa(job #1256509)

Utilizator MarcvsHdrMihai Leonte MarcvsHdr Data 6 noiembrie 2014 13:41:44
Problema Struti Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.34 kb
#include <iostream>
#include <fstream>

#include <algorithm>
#include <vector>

#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) > (b) ? (b) : (a))

int n, m, p;
short int max[1000][1000][10];
short int min[1000][1000][10];

void split(int r, int c,
           int radd, int cadd,
           std::vector<int>& ro,
           std::vector<int>& co,
           std::vector<int>& ko) {
  int k = 0;
  while (r >= (1 << (k + 1)) && c >= (1 << (k + 1))) {
    k++;
  }
  ro.push_back(radd);
  co.push_back(cadd);
  ko.push_back(k);

  // Call recursively twice.
  if (r - (1 << k) > 0) {
    split(r - (1 << k), c, radd - (1 << k), cadd, ro, co, ko);
  }

  if (c - (1 << k) > 0) {
    split((1 << k), c - (1 << k), radd, cadd - (1 << k), ro, co, ko);
  }
}

void scan(int dx, int dy, int& sol, int& count) {
  std::vector<int> r;
  std::vector<int> c;
  std::vector<int> k;
  split(dx, dy, 0, 0, r, c, k);

  for (int i = dx - 1; i < n; ++i) {
    for (int j = dy - 1; j < m; ++j) {
      int maxloc = 0;
      int minloc = 1000000;
      for (int t = 0; t < r.size(); ++t) {
        maxloc = MAX(maxloc, max[i + r[t]][j + c[t]][k[t]]);
        minloc = MIN(minloc, min[i + r[t]][j + c[t]][k[t]]);
      }

//      std::cerr << "At (" << i << ", " << j << ") MAXLOC,MINLOC = " << maxloc <<
//          ", " << minloc << " for a rectangle of size: " << dx << ", " << dy <<
//          std::endl;

      if (maxloc - minloc == sol) {
        count++;
      } else if (maxloc - minloc < sol) {
        sol = maxloc - minloc;
        count = 1;
      }
    }
  }
}

int main()
{
  std::ifstream in("struti.in");
  std::ofstream out("struti.out");

  in >> n >> m >> p;
  // Fill out the initial min and max.
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      in >> max[i][j][0];
      min[i][j][0] = max[i][j][0];
    }
  }

  // Fill out the rest.
  for (int k = 1; k <= 9; ++k) {
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < m; ++j) {
        // Max
        max[i][j][k] = max[i][j][k - 1];
        if (i - (1 << (k - 1)) >= 0) {
          max[i][j][k] =
              std::max(max[i][j][k], max[i - (1 << (k - 1))][j][k - 1]);
        }
        if (j - (1 << (k - 1)) >= 0) {
          max[i][j][k] =
              std::max(max[i][j][k], max[i][j - (1 << (k - 1))][k - 1]);
        }
        if (i - (1 << (k - 1)) >= 0 && j - (1 << (k - 1)) >= 0) {
          max[i][j][k] =
              std::max(max[i][j][k],
                       max[i - (1 << (k - 1))][j - (1 << (k - 1))][k - 1]);
        }
        // Min
        min[i][j][k] = min[i][j][k - 1];
        if (i - (1 << (k - 1)) >= 0) {
          min[i][j][k] =
              std::min(min[i][j][k], min[i - (1 << (k - 1))][j][k - 1]);
        }
        if (j - (1 << (k - 1)) >= 0) {
          min[i][j][k] =
              std::min(min[i][j][k], min[i][j - (1 << (k - 1))][k - 1]);
        }
        if (i - (1 << (k - 1)) >= 0 && j - (1 << (k - 1)) >= 0) {
          min[i][j][k] =
              std::min(min[i][j][k],
                       min[i - (1 << (k - 1))][j - (1 << (k - 1))][k - 1]);
        }
      }
    }
  }

  for (int i = 0; i < p; ++i) {
    int dx, dy;
    in >> dx >> dy;
    int sol = 1000000;
    int count = 0;
    scan(dx, dy, sol, count);
    if (dx != dy) {
      scan(dy, dx, sol, count);
    }

    out << sol << " " << count << std::endl;
  }

  in.close();
  out.close();

  return 0;
}