Cod sursa(job #2133446)

Utilizator flibiaVisanu Cristian flibia Data 16 februarie 2018 23:13:43
Problema Struti Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.25 kb
#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, freqmin[8 * N], freqmax[8 * N];
int col_min[N][4 * N], col_max[N][4 * 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 update(int id, int st, int dr, int pos, int idx, int val){
		if(st == dr){
		col_min[id][pos] = val;
		col_max[id][pos] = val;
		return;
	}
	int mid = (st + dr) >> 1;
	if(idx <= mid)
		update(id, st, mid, L, idx, val);
	else update(id, mid + 1, dr, R, idx, val);
	col_min[id][pos] = min(col_min[id][L], col_min[id][R]);
	col_max[id][pos] = max(col_max[id][L], col_max[id][R]);
}

int query_max(int id, int st, int dr, int pos, int l, int r){
	if(l <= st && dr <= r)
		return col_max[id][pos];
	int mid = (st + dr) >> 1;
	int left, right;
	left = right = 0;
	if(l <= mid)
		left = query_max(id, st, mid, L, l, r);
	if(r > mid)
		right = query_max(id, mid + 1, dr, R, l, r);
	return max(left, right);
}

int query_min(int id, int st, int dr, int pos, int l, int r){
	if(l <= st && dr <= r)
		return col_min[id][pos];
	int mid = (st + dr) >> 1;
	int left, right;
	left = right = INF;
	if(l <= mid)
		left = query_min(id, st, mid, L, l, r);
	if(r > mid)
		right = query_min(id, mid + 1, dr, R, l, r);
	return min(left, right);
}

void solve(int dx, int dy){
	set <int> minset, maxset;
	for(int i = 1; i + dx - 1 <= n; i++){
		memset(freqmin, 0, sizeof freqmin);
		memset(freqmax, 0, sizeof freqmax);
		minset.clear();
		maxset.clear();
		int mx = 0, mn = INF, gg, wp;
		for(int j = 1; j <= dy; j++){
			gg = query_max(j, 1, n, 1, i, i + dx - 1);
			wp = query_min(j, 1, n, 1, i, i + dx - 1);
			if(++freqmax[gg] == 1)
				maxset.insert(-gg);
			if(++freqmin[wp] == 1)
				minset.insert(wp);
		}
		mx = -(*maxset.begin());
		mn = *minset.begin();
		if(mx - mn == bst)
			cnt++;
		else if(mx - mn < bst){
			bst = mx - mn;
			cnt = 1;
		}
		for(int j = 2; j + dy - 1 <= m; j++){
			gg = query_max(j + dy - 1, 1, n, 1, i, i + dx - 1);
			wp = query_min(j + dy - 1, 1, n, 1, i, i + dx - 1);
			if(++freqmax[gg] == 1)
				maxset.insert(-gg);
			if(++freqmin[wp] == 1)
				minset.insert(wp);
			gg = query_max(j - 1, 1, n, 1, i, i + dx - 1);
			wp = query_min(j - 1, 1, n, 1, i, i + dx - 1);
			if(--freqmax[gg] == 0)
				maxset.erase(maxset.find(-gg));
			if(--freqmin[wp] == 0)
				minset.erase(minset.find(wp));
			mx = -(*maxset.begin());
			mn = *minset.begin();
			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(x);
			update(j, 1, n, 1, i, x);
		}
	while(q--){
		read(x); read(y);
		bst = INF; cnt = 0;
		solve(x, y);
		if(x != y)
			solve(x, y);
		cout << bst << ' ' << cnt << '\n'; 
	}
	return 0;
}