Cod sursa(job #2208632)

Utilizator DawlauAndrei Blahovici Dawlau Data 30 mai 2018 19:28:29
Problema Struti Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4 kb
#include <fstream>
#include <deque>
#include <climits>

using namespace std;

ifstream fin("struti.in");
ofstream fout("struti.out");

typedef unsigned int Natural;
const Natural maxSZ = 1005, Inf = UINT_MAX;

class InParser {

	private:
		
		ifstream File;
		static const Natural buffSZ = (1 << 15);
		char buff[buffSZ];
		Natural buffPos;

		void _advance() {

			if (++buffPos == buffSZ) {

				buffPos = 0;
				File.read(buff, buffSZ);
			}
		}

	public:

		InParser& operator >>(Natural &no) {

			while (!isdigit(buff[buffPos]))
				_advance();
			no = 0;
			while (isdigit(buff[buffPos])) {

				no = no * 10 + buff[buffPos] - '0';
				_advance();
			}
			return *this;
		}
};

Natural rows, cols, Q;
Natural Grid[maxSZ][maxSZ], maxGrid[maxSZ][maxSZ], minGrid[maxSZ][maxSZ];
deque <Natural> minDeque, maxDeque;
Natural minDiff, cnt;

void readData() {

	fin >> rows >> cols >> Q;

	for (Natural row = 1; row <= rows; ++row)
		for (Natural col = 1; col <= cols; ++col)
			fin >> Grid[row][col];
}

inline void buildMinMax_Grid(const Natural &rectRows, const Natural &rectCols) {

	for (Natural row = 1; row <= rows; ++row) {

		for (Natural col = 1; col < rectCols; ++col) {

			while (!minDeque.empty() && Grid[row][minDeque.back()] > Grid[row][col])
				minDeque.pop_back();
			minDeque.push_back(col);

			while (!maxDeque.empty() && Grid[row][maxDeque.back()] < Grid[row][col])
				maxDeque.pop_back();
			maxDeque.push_back(col);
		}

		for (Natural col = rectCols; col <= cols; ++col) {

			while (!minDeque.empty() && Grid[row][minDeque.back()] > Grid[row][col])
				minDeque.pop_back();
			minDeque.push_back(col);

			while (!maxDeque.empty() && Grid[row][maxDeque.back()] < Grid[row][col])
				maxDeque.pop_back();
			maxDeque.push_back(col);

			maxGrid[row][col - rectCols + 1] = Grid[row][maxDeque.front()];
			minGrid[row][col - rectCols + 1] = Grid[row][minDeque.front()];

			while (minDeque.front() < col - rectCols + 2)
				minDeque.pop_front();
			while (maxDeque.front() < col - rectCols + 2)
				maxDeque.pop_front();
		}
		maxDeque.clear(); minDeque.clear();
	}
}

inline void contorRects(const Natural &rectRows, const Natural &rectCols) {

	for (Natural col = 1; col <= cols - rectCols + 1; ++col) {

		for (Natural row = 1; row < rectRows; ++row) {

			while (!minDeque.empty() && minGrid[minDeque.back()][col] > minGrid[row][col])
				minDeque.pop_back();
			minDeque.push_back(row);

			while (!maxDeque.empty() && maxGrid[maxDeque.back()][col] < maxGrid[row][col])
				maxDeque.pop_back();
			maxDeque.push_back(row);
		}

		for (Natural row = rectRows; row <= rows; ++row) {

			while (!minDeque.empty() && minGrid[minDeque.back()][col] > minGrid[row][col])
				minDeque.pop_back();
			minDeque.push_back(row);

			while (!maxDeque.empty() && maxGrid[maxDeque.back()][col] < maxGrid[row][col])
				maxDeque.pop_back();
			maxDeque.push_back(row);

			if (maxGrid[maxDeque.front()][col] - minGrid[minDeque.front()][col] < minDiff) {

				minDiff = maxGrid[maxDeque.front()][col] - minGrid[minDeque.front()][col];
				cnt = 1;
			}
			else if (maxGrid[maxDeque.front()][col] - minGrid[minDeque.front()][col] == minDiff)
				++cnt;

			while (minDeque.front() < row - rectRows + 2)
				minDeque.pop_front();
			while (maxDeque.front() < row - rectRows + 2)
				maxDeque.pop_front();
		}
		maxDeque.clear(); minDeque.clear();
	}
}

inline pair <Natural, Natural> getRects(const Natural &rectRows, const Natural &rectCols) {

	minDiff = Inf, cnt = 0;
	buildMinMax_Grid(rectRows, rectCols);
	contorRects(rectRows, rectCols);
	buildMinMax_Grid(rectCols, rectRows);
	contorRects(rectCols, rectRows);
	
	return {minDiff, cnt};
}

int main() {

	readData();

	while (Q--) {

		Natural rectRows, rectCols;
		fin >> rectRows >> rectCols;

		pair <Natural, Natural> Rects = getRects(rectRows, rectCols);
		if (rectRows == rectCols)
			Rects.second >>= 1;
		fout << Rects.first << ' ' << Rects.second << '\n';
	}
}