Cod sursa(job #2021769)

Utilizator Stefan_RaduStefan Radu Stefan_Radu Data 14 septembrie 2017 17:51:56
Problema Struti Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.94 kb
#include <fstream>
#include <vector>
#include <deque>

using namespace std;

ifstream cin("struti.in");
ofstream cout("struti.out");

const int MAX = 1e3 + 17;
deque < int > deq_min;
deque < int > deq_max;
vector < vector < int > > sol_max(MAX, vector < int > (MAX));
vector < vector < int > > sol_min(MAX, vector < int > (MAX));
vector < vector < int > > sol2_min(MAX, vector < int > (MAX));
vector < vector < int > > sol2_max(MAX, vector < int > (MAX));

int count (int sol, int n, int m, int x, int y) {
  int cnt = 0;
  for (int i = 1; i <= n - y + 1; i ++) {
    for (int j = 1; j <= m - x + 1; j ++) {
      if (sol2_max[i][j] - sol2_min[i][j] == sol) {
        cnt ++;
      }
    }
  }

  return cnt;
}

pair < int, int > solve(int x, int y, int n, int m, vector < vector < int > > &mat) {

  for (int i = 1; i <= n; i ++) {
    deq_min.clear();
    deq_max.clear();
    for (int j = 1; j <= x; j ++) {
      while (deq_min.size() and mat[i][j] <= mat[i][deq_min.back()]) {
        deq_min.pop_back();
      }
      while (deq_max.size() and mat[i][j] >= mat[i][deq_max.back()]) {
        deq_max.pop_back();
      }

      deq_min.push_back(j);
      deq_max.push_back(j);
    }
    
    sol_min[i][1] = mat[i][deq_min.front()];
    sol_max[i][1] = mat[i][deq_max.front()];

    for (int j = x + 1; j <= m; j ++) {
      
      if (deq_min.front() <= j - x) {
        deq_min.pop_front();
      }
      if (deq_max.front() <= j - x) {
        deq_max.pop_front();
      }

      while (deq_min.size() and mat[i][j] <= mat[i][deq_min.back()]) {
        deq_min.pop_back();
      }
      while (deq_max.size() and mat[i][j] >= mat[i][deq_max.back()]) {
        deq_max.pop_back();
      }

      deq_min.push_back(j);
      deq_max.push_back(j);
      sol_min[i][j - x + 1] = mat[i][deq_min.front()];
      sol_max[i][j - x + 1] = mat[i][deq_max.front()];
    }
  }

  for (int j = 1; j <= m - x + 1; j ++) {
    deq_min.clear();
    deq_max.clear(); 

    for (int i = 1; i <= y; i ++) {
      while (deq_min.size() and sol_min[i][j] <= sol_min[deq_min.back()][j]) {
        deq_min.pop_back();
      }
      while (deq_max.size() and sol_max[i][j] >= sol_max[deq_max.back()][j]) {
        deq_max.pop_back();
      }

      deq_min.push_back(i);
      deq_max.push_back(i);
    }

    sol2_min[1][j] = sol_min[deq_min.front()][j];
    sol2_max[1][j] = sol_max[deq_max.front()][j];

    for (int i = y + 1; i <= n; i ++) {
      
      if (deq_min.front() <= i - y) {
        deq_min.pop_front();
      }
      if (deq_max.front() <= i - y) {
        deq_max.pop_front();
      }

      while (deq_min.size() and sol_min[i][j] <= sol_min[deq_min.back()][j]) {
        deq_min.pop_back();
      }
      while (deq_max.size() and sol_max[i][j] >= sol_max[deq_max.back()][j]) {
        deq_max.pop_back();
      }

      deq_min.push_back(i);
      deq_max.push_back(i);
      sol2_min[i - y + 1][j] = sol_min[deq_min.front()][j];
      sol2_max[i - y + 1][j] = sol_max[deq_max.front()][j];
    }
  }

  int sol = 1e5;

  for (int i = 1; i <= n - y + 1; i ++) {
    for (int j = 1; j <= m - x + 1; j ++) {
      if (sol2_max[i][j] - sol2_min[i][j] < sol) {
        sol = sol2_max[i][j] - sol2_min[i][j];
      }
    }
  }

  int cnt = count(sol, n, m, x, y);

  return {sol, cnt};
}

int main() {
  int n, m, p;
  cin >> n >> m >> p;

  vector < vector < int > > mat(n + 1, vector < int > (m + 1));
  for (int i = 1; i <= n; i ++) {
    for (int j = 1; j <= m; j ++) {
      cin >> mat[i][j];
    }
  }

  for (int i = 1; i <= p; i ++) {
    int x, y;
    cin >> x >> y;

    pair < int, int > sol1 = solve(x, y, n, m, mat);
    if (x == y) {
      cout << sol1.first << ' ' << sol1.second << '\n';
      continue;
    }

    pair < int, int > sol2 = solve(y, x, n, m, mat);

    if (sol1.first == sol2.first) {
      cout << sol1.first << ' ' << sol1.second + sol2.second << '\n';
      continue;
    }

    if (sol1.first > sol2.first) {
      swap(sol1, sol2);
    }
    cout << sol1.first << ' ' << sol1.second << '\n';
  } 
}