Cod sursa(job #2256887)

Utilizator oldatlantianSerban Cercelescu oldatlantian Data 9 octombrie 2018 12:30:27
Problema Matrice 2 Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.65 kb
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;

ifstream fi("matrice2.in");
ofstream fo("matrice2.out");

using pii = pair<int, int>;

const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};
const int N = 305, LG = 17;

vector<int> g[N * N];
int mx[N][N], lvl[N * N], val[N * N], dsu[N * N], far[LG][N * N], mn_far[LG][N * N];

vector<int> nodes;
int n, q;

static int get_far(int u) {
	return (dsu[u] ? (dsu[u] = get_far(dsu[u])) : u); }

static bool join(int a, int b) {
	a = get_far(a);
	b = get_far(b);
	if (a == b)
		return false;
	if (rand() % 2)
		swap(a, b);
	dsu[a] = b;
	return true; }

static pii get_pos(int cod) {
	cod-= 1;
	return pii(cod / n + 1, cod % n + 1); }

static int get_cod(int x, int y) {
	return (x - 1) * n + y;  }

static bool ok(int x, int y) {
	return (1 <= min(x, y) && max(x, y) <= n); }

static void build_mst() {
	nodes.resize(n * n);
	iota(begin(nodes), end(nodes), 1);
	sort(begin(nodes), end(nodes), [&](const int &a, const int &b) {
		pii pa(get_pos(a)), pb(get_pos(b));
		return mx[pa.x][pa.y] > mx[pb.x][pb.y]; });

	for (auto i: nodes) {
		pii pos = get_pos(i);
		int nx, ny, him;

		for (int dir = 0; dir < 4; ++dir) {
			nx = pos.x + dx[dir];
			ny = pos.y + dy[dir];
			him = get_cod(nx, ny);

			if (!ok(nx, ny))
				continue;
			if (val[him] < val[i])
				continue;

			him = get_cod(nx, ny);
			if (join(i, him)) {
				g[i].push_back(him);
				g[him].push_back(i); } } } }

static void dfs(int u, int pap = 0) {
	far[0][u] = pap;
	mn_far[0][u] = val[u];
	for (auto v: g[u]) if (v != pap) {
		lvl[v] = lvl[u] + 1;
		dfs(v, u); } }

static void build_rmq() {
	for (int lg = 1; lg < LG; ++lg)
	for (int i = 1; i <= n * n; ++i) {
		mn_far[lg][i] = min(mn_far[lg - 1][i], mn_far[lg - 1][far[lg - 1][i]]);
		far[lg][i] = far[lg - 1][far[lg - 1][i]]; } }

static int query(int a, int b) {
	if (a == b)
		return val[a];
	if (lvl[a] < lvl[b])
		swap(a, b);

	int ant = min(val[a], val[b]);
	for (int lg = 0; lg < LG; ++lg)
		if ((lvl[a] - lvl[b]) & (1 << lg)) {
			ant = min(ant, mn_far[lg][a]);
			a = far[lg][a]; }

	if (a == b)
		return ant;

	for (int lg = LG - 1; lg >= 0; --lg)
		if (far[lg][a] != far[lg][b]) {
			ant = min(ant, mn_far[lg][a]);
			ant = min(ant, mn_far[lg][b]);
			a = far[lg][a];
			b = far[lg][b]; }
	ant = min(ant, mn_far[0][a]);
	ant = min(ant, mn_far[0][b]);

	return min(ant, ant); }

int main() {
	int x1, x2, y1, y2;

	fi >> n >> q;
	for (int t = 1, i = 1; i <= n; ++i)
	for (int j = 1; j <= n; ++j, ++t) {
		fi >> mx[i][j];
		val[t] = mx[i][j]; }

	build_mst();
	dfs(1);
	build_rmq();	

	while (q--) {
		fi >> x1 >> y1 >> x2 >> y2;
		fo << query(get_cod(x1, y1), get_cod(x2, y2)) << '\n'; }

	return 0; }