Cod sursa(job #1256481)

Utilizator MarcvsHdrMihai Leonte MarcvsHdr Data 6 noiembrie 2014 12:55:25
Problema Struti Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.8 kb
#include <iostream>
#include <fstream>

#include <algorithm>
#include <vector>

template<int (*comp)(int, int), int def>
struct TwoDSegTree {
  int n, m;
  std::vector<int> v;

  // Assumes the entire matrix is 0 in the beginning.
  TwoDSegTree(int n, int m) : n(n), m(m), v(1 + 8 * n * m, def) {}

  inline void set(int i, int j, int val) {
    set_elem(1, 1, n, 1, m, i, j, val);
  }

  inline int get(int rli, int rlf, int cli, int clf) {
    return get_elem(1, 1, n, 1, m, rli, rlf, cli, clf);
  }

  int get_elem(int node,
               int rowli, int rowlf,
               int colli, int collf,
               int rli, int rlf,
               int cli, int clf) {
    // Area doesn't overlap with current node.
    if (rli > rowlf || rlf < rowli || cli > collf || clf < colli) {
      return def;
    }

    // Area covers current node.
    if (rli <= rowli && rlf >= rowlf && cli <= colli && clf >= collf) {
      return v[node];
    }

    // Split into four areas.
    int sol = def;
    sol = comp(sol, get_elem(node * 4 - 2,
                             rowli, (rowli + rowlf) / 2,
                             colli, (colli + collf) / 2,
                             rli, rlf, cli, clf));
    sol = comp(sol, get_elem(node * 4 - 1,
                             rowli, (rowli + rowlf) / 2,
                             (colli + collf) / 2 + 1, collf,
                             rli, rlf, cli, clf));
    sol = comp(sol, get_elem(node * 4 - 0,
                             (rowli + rowlf) / 2 + 1, rowlf,
                             colli, (colli + collf) / 2,
                             rli, rlf, cli, clf));
    sol = comp(sol, get_elem(node * 4 + 1,
                             (rowli + rowlf) / 2 + 1, rowlf,
                             (colli + collf) / 2 + 1, collf,
                             rli, rlf, cli, clf));
    return sol;
  }

  int set_elem(int node,
               int rowli, int rowlf,
               int colli, int collf,
               int row, int col, int val) {
    // Out of bounds (shouldn't really happen, but alas).
    if (row < rowli || row > rowlf || col < colli || col > collf) {
      return def;
    }

    // Strict bounds.
    if (row == rowli && row == rowlf && col == colli && col == collf) {
      v[node] = val;
      return val;
    }

    // Split into four quads.
    if (row <= (rowli + rowlf) / 2) {
      if (col <= (colli + collf) / 2) {
        v[node] = comp(v[node], set_elem(node * 4 - 2,
                                         rowli, (rowli + rowlf) / 2,
                                         colli, (colli + collf) / 2,
                                         row, col, val));
      } else {
        v[node] = comp(v[node], set_elem(node * 4 - 1,
                                         rowli, (rowli + rowlf) / 2,
                                         (colli + collf) / 2 + 1, collf,
                                         row, col, val));
      }
    } else {
      if (col <= (colli + collf) / 2) {
        v[node] = comp(v[node], set_elem(node * 4 + 0,
                                         (rowli + rowlf) / 2 + 1, rowlf,
                                         colli, (colli + collf) / 2,
                                         row, col, val));
      } else {
        v[node] = comp(v[node], set_elem(node * 4 + 1,
                                         (rowli + rowlf) / 2 + 1, rowlf,
                                         (colli + collf) / 2 + 1, collf,
                                         row, col, val));
      }
    }
  }
};

inline int fmax(int a, int b) {
  return a > b ? a : b;
}

inline int fmin(int a, int b) {
  return a < b ? a : b;
}

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

  int n, m, p;
  in >> n >> m >> p;
  TwoDSegTree<fmax, 0> max(n, m);
  TwoDSegTree<fmin, 1000000> min(n, m);
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      int x;
      in >> x;
      max.set(i, j, x);
      min.set(i, j, x);
    }
  }

  for (int i = 0; i < p; ++i) {
    int dx, dy;
    in >> dx >> dy;
    int sol = 1000000;
    int count = 0;
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= m; ++j) {
        if (i >= dx && j >= dy) {
          int dif = max.get(i - dx + 1, i, j - dy + 1, j) -
                    min.get(i - dx + 1, i, j - dy + 1, j);
          if (dif == sol) {
            count++;
          } else if (dif < sol) {
            count = 1;
            sol = dif;
          }
        }
        if (i >= dy && j >= dx && dy != dx) {
          int dif = max.get(i - dy + 1, i, j - dx + 1, j) -
                    min.get(i - dy + 1, i, j - dx + 1, j);
          if (dif == sol) {
            count++;
          } else if (dif < sol) {
            count = 1;
            sol = dif;
          }
        }
      }
    }
    out << sol << " " << count << std::endl;
  }

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

  return 0;
}