Cod sursa(job #1588293)

Utilizator iordache.bogdanIordache Ioan-Bogdan iordache.bogdan Data 2 februarie 2016 22:27:15
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.66 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;

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

const int dx[] = { 1, -1, 0, 0 };
const int dy[] = { 0, 0, 1, -1 };

struct Query {

	int x1, y1, x2, y2;
	int index;

	Query() {}

	Query(int x1, int y1, int x2, int y2, int index) {
		this->x1 = x1;
		this->y1 = y1;
		this->x2 = x2;
		this->y2 = y2;
		this->index = index;
	}

};

vector<Query> queries;

int a[305][305], b[305][305], sol[20005], disJoint[305 * 305];

vector< pair<int, int> > v;

inline bool comp1(const pair<int, int> &i, const pair<int, int> &j) {

	return a[i.first][i.second] > a[j.first][j.second];

}

inline bool comp2(const Query &i, const Query &j) {

	return sol[i.index] > sol[j.index];

}

inline int root(int node) {

	int x = node;

	while (disJoint[node] >= 0)
		node = disJoint[node];

	swap(x, node);

	while (node != x) {
		int tmp = disJoint[node];
		disJoint[node] = x;
		node = tmp;
	}

	return x;

}

inline void join(int node1, int node2) {

	int root1 = root(node1);
	int root2 = root(node2);

	if (root1 == root2)
		return;

	if (disJoint[root1] <= disJoint[root2]) {

		disJoint[root1] += disJoint[root2];
		disJoint[root2] = root1;

	}
	else {

		disJoint[root2] += disJoint[root1];
		disJoint[root1] = root2;

	}

}

int main() {

	int n, q;
	fin >> n >> q;

	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {

			fin >> a[i][j];
			v.push_back(make_pair(i, j));

		}
	}

	sort(v.begin(), v.end(), comp1);

	for (int i = 1; i <= q; ++i) {

		int x1, y1, x2, y2;
		fin >> x1 >> y1 >> x2 >> y2;

		queries.push_back(Query(x1, y1, x2, y2, i));

	}

	for (int step = (1 << 20); step; step >>= 1) {

		sort(queries.begin(), queries.end(), comp2);

		memset(b, 0, sizeof b);

		for (unsigned int i = 0; i <= v.size(); ++i)
			disJoint[i] = -1;
		
		for (int i = 0, j = 0, curr = 0; j < (int)queries.size(); ++j) {

			while (i < (int)v.size() && sol[queries[j].index] + step <= a[v[i].first][v[i].second]) {

				int x = v[i].first;
				int y = v[i].second;

				b[x][y] = ++curr;

				for (int d = 0; d < 4; ++d) {

					int nextX = x + dx[d];
					int nextY = y + dy[d];

					if (b[nextX][nextY] == 0)
						continue;

					join(b[x][y], b[nextX][nextY]);

				}

				++i;

			}

			int aux = root(b[queries[j].x1][queries[j].y1]);
			if (aux && aux == root(b[queries[j].x2][queries[j].y2]))
				sol[queries[j].index] += step;

		}

	}

	for (int i = 1; i <= q; ++i)
		fout << sol[i] << '\n';

	return 0;

}

//Trust me, I'm the Doctor!