Pagini recente » Cod sursa (job #910338) | Cod sursa (job #1969092) | Cod sursa (job #2320762) | Cod sursa (job #2615763) | Cod sursa (job #2804836)
/*
Pirnog Theodor Ioan
Colegiul National "B. P. Hasdeu"
*/
#include <fstream>
#include <deque>
using namespace std;
ifstream cin("struti.in");
ofstream cout("struti.out");
const int NMAX = 1e3;
int minim_linie[NMAX + 1][NMAX + 1], maxim_linie[NMAX + 1][NMAX + 1], minim_submat[NMAX + 1][NMAX + 1], maxim_submat[NMAX + 1][NMAX + 1];
int n, m, p, dx, dy, a[NMAX + 1][NMAX + 1];
void read(){
cin >> n >> m >> p;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> a[i][j];
}
void clear(){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
minim_linie[i][j] = maxim_linie[i][j] = 0;
minim_submat[i][j] = maxim_submat[i][j] = 0;
}
}
}
void build_min_lin(){
// construiesc minimele pe fiecare linie, avand grija la faptul ca imi este impusa o anumita lungime pentru secventa
for(int i = 1; i <= n; i++){
deque <int> dq;
for(int j = 1; j <= m; j++){
while(!dq.empty() && a[i][j] <= a[i][dq.back()])
dq.pop_back();
dq.push_back(j);
while(!dq.empty() && dq.front() <= j - dy)
dq.pop_front();
if(dq.back() >= dy)
minim_linie[i][j] = a[i][dq.front()];
}
}
}
void build_max_lin(){
// construiesc maximele pe linie, avand grija la faptul ca imi este impusa o anumita lungime pentru secventa
for(int i = 1; i <= n; i++){
deque <int> dq;
for(int j = 1; j <= m; j++){
while(!dq.empty() && a[i][j] >= a[i][dq.back()])
dq.pop_back();
dq.push_back(j);
while(!dq.empty() && dq.front() <= j - dy)
dq.pop_front();
if(dq.back() >= dy)
maxim_linie[i][j] = a[i][dq.front()];
}
}
}
void build_min(){
// parcurgerea se va face acum pe coloane, intrucat trebuie sa am o legatura intre minimele si maximele pe linii
// minim_submat[i][j] va fi valoarea minima din matricea de colt dreapta jos (i, j) si cu laturile dx (sau dy)
for(int j = 1; j <= m; j++){
deque <int> dq;
for(int i = 1; i <= n; i++){
while(!dq.empty() && minim_linie[i][j] <= minim_linie[dq.back()][j])
dq.pop_back();
dq.push_back(i);
while(!dq.empty() && dq.front() <= i - dx)
dq.pop_front();
if(i >= dx)
minim_submat[i][j] = minim_linie[dq.front()][j];
}
}
}
void build_max(){
// parcurgerea se va face acum pe coloane, intrucat trebuie sa am o legatura intre minimele si maximele pe linii
// minim_submat[i][j] va fi valoarea minima din matricea de colt dreapta jos (i, j) si cu laturile dx (sau dy)
for(int j = 1; j <= m; j++){
deque <int> dq;
for(int i = 1; i <= n; i++){
while(!dq.empty() && maxim_linie[i][j] >= maxim_linie[dq.back()][j])
dq.pop_back();
dq.push_back(i);
while(!dq.empty() && dq.front() <= i - dx)
dq.pop_front();
if(i >= dx)
maxim_submat[i][j] = maxim_linie[dq.front()][j];
}
}
}
void compare(int &dif_min, int &k){
// caut oferta cea mai convenabila(de diferenta minima) si numarul de oferte existente cu aceasta diferenta
int dif = 0;
for(int i = dx; i <= n; i++){
for(int j = dy; j <= m; j++){
dif = maxim_submat[i][j] - minim_submat[i][j];
if(dif < dif_min){
dif_min = dif;
k = 1;
}else if(dif == dif_min)
k++;
}
}
}
void build(int &dif_min, int &k){
clear();
build_min_lin();
build_max_lin();
build_min();
build_max();
compare(dif_min, k);
}
void solve(){
int dif_min = 0, k = 0;
for(int i = 1; i <= p; i++){
dif_min = int(1e9);
k = 0;
cin >> dx >> dy;
build(dif_min, k);
if(dx != dy){
swap(dx, dy);
build(dif_min, k);
}
cout << dif_min << " " << k << "\n";
}
}
int main(){
read();
solve();
}