Cod sursa(job #2133524)

Utilizator flibiaVisanu Cristian flibia Data 17 februarie 2018 01:26:02
Problema Struti Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.25 kb
//P * N^2 * log2(N) ar trebui sa intre 
#pragma GCC optimize("03")
#include <bits/stdc++.h>
#define N 1003
#define L (pos << 1)
#define R (L | 1)
#define INF 8001

using namespace std;

int n, m, x, y, q, bst, cnt, a[N][N], freqmin[8 * N], freqmax[8 * N];
int blocks_min[N][N], blocks_max[N][N];

#define dim 100000
char buff[dim];
int p = 0;

void read(int &nr){
	nr = 0;
	while(buff[p] < '0' || buff[p] > '9')
		if(++p == dim)
			fread(buff, 1, dim, stdin), p = 0;
	while(buff[p] >= '0' && buff[p] <= '9'){
		nr = 10 * nr + buff[p] - '0';
		if(++p == dim)
			fread(buff, 1, dim, stdin), p = 0;
	}
}

void build_blocks(int sz){
	memset(blocks_max, 0, sizeof blocks_max);
	memset(blocks_min, 0, sizeof blocks_min);
	deque <int> dqmax, dqmin;
	for(int j = 1; j <= m; j++){
		dqmax.clear();
		dqmin.clear();
		for(int i = 1; i <= sz; i++){
			while(!dqmax.empty() && a[dqmax.back()][j] <= a[i][j])
				dqmax.pop_back();
			dqmax.push_back(i);
			while(!dqmin.empty() && a[dqmin.back()][j] >= a[i][j])
				dqmin.pop_back();
			dqmin.push_back(i);
		}
		blocks_max[1][j] = a[dqmax.front()][j];
		blocks_min[1][j] = a[dqmin.front()][j];
		for(int i = sz + 1; i <= n; i++){
			while(!dqmax.empty() && a[dqmax.back()][j] <= a[i][j])
				dqmax.pop_back();
			dqmax.push_back(i);
			while(!dqmax.empty() && dqmax.front() < i - sz + 1)
				dqmax.pop_front();
			while(!dqmin.empty() && a[dqmin.back()][j] >= a[i][j])
				dqmin.pop_back();
			dqmin.push_back(i);
			while(!dqmin.empty() && dqmin.front() < i - sz + 1)
				dqmin.pop_front();
			blocks_max[i - sz + 1][j] = a[dqmax.front()][j];
			blocks_min[i - sz + 1][j] = a[dqmin.front()][j];
		}
	}
}

void solve(int dx, int dy){
	build_blocks(dx);
	deque <int> dqmax, dqmin;
	int mx, mn;
	for(int i = 1; i + dx - 1 <= n; i++){
		dqmax.clear();
		dqmin.clear();
		for(int j = 1; j <= dy; j++){
			while(!dqmax.empty() && blocks_max[i][dqmax.back()] <= blocks_max[i][j])
				dqmax.pop_back();
			dqmax.push_back(j);
			while(!dqmin.empty() && blocks_min[i][dqmin.back()] >= blocks_min[i][j])
				dqmin.pop_back();
			dqmin.push_back(j);
		}
		mx = blocks_max[i][dqmax.front()];
		mn = blocks_min[i][dqmin.front()];
		if(mx - mn == bst)
			cnt++;
		else if(mx - mn < bst){
			bst = mx - mn;
			cnt = 1;
		}
		for(int j = dy + 1; j <= m; j++){
			while(!dqmax.empty() && blocks_max[i][dqmax.back()] <= blocks_max[i][j])
				dqmax.pop_back();
			dqmax.push_back(j);
			while(!dqmax.empty() && dqmax.front() < j - dy + 1)
				dqmax.pop_front();
			while(!dqmin.empty() && blocks_min[i][dqmin.back()] >= blocks_min[i][j])
				dqmin.pop_back();
			dqmin.push_back(j);
			while(!dqmin.empty() && dqmin.front() < j - dy + 1)
				dqmin.pop_front();
			mx = blocks_max[i][dqmax.front()];
			mn = blocks_min[i][dqmin.front()];
			if(mx - mn == bst)
				cnt++;
			else if(mx - mn < bst){
				bst = mx - mn;
				cnt = 1;
			}
		}
	}
}

int main(){
	freopen("struti.in", "r", stdin);
	freopen("struti.out", "w", stdout);
	read(n); read(m); read(q);
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			read(a[i][j]);
	while(q--){
		read(x); read(y);
		bst = INF; cnt = 0;
		solve(x, y);
		if(x != y)
			solve(y, x);
		cout << bst << ' ' << cnt << '\n'; 
	}
	return 0;
}