Cod sursa(job #321826)

Utilizator raduzerRadu Zernoveanu raduzer Data 7 iunie 2009 15:22:20
Problema Matrice 2 Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.39 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;

#define pb push_back
#define mp make_pair
#define x first
#define y second
#define forit(it, v) for (typeof(v.begin()) it = v.begin(); it != v.end(); ++it)

const int MAX_N = 300;
const int pow = 17;

int dir[4];

int n, m, root;
int f[MAX_N * MAX_N];
int val[MAX_N * MAX_N];
int t[MAX_N * MAX_N];
vector < pair <int, int> > v;
vector <int> fiu[MAX_N * MAX_N];

int lvl[MAX_N * MAX_N];
int b[pow][MAX_N * MAX_N];

int find(int nod)
{
	if (t[nod] == nod) return nod;
	return find(t[nod]);
}

void join(int c1, int c2)
{
	t[c1] = c2;
}

inline int lg(int x) { return (x >> 1) ? lg(x >> 1) + 1 : 0; }
inline int lsb(int x) { return ((x ^ (x - 1)) + 1) >> 1; }

void build_tree()
{
	int i, c1, c2;

	forit(it, v)
	{
		t[it->y] = it->y;
		f[it->y] = 1;
		for (i = 0; i < 4; ++i)
		{
			int x = it->y + dir[i];

			if (x < 0 || x >= n * n || (it->y / n != x / n && it->y % n != x % n)) continue;

			if (f[x] && (c1 = find(x)) != (c2 = find(it->y)))
				join(c1, c2);
		}
	}
}

void df(int nod)
{
	if (f[nod]) return;
	f[nod] = 1;
	
	b[0][nod] = t[nod];
	
	for (int i = 1; i < pow; ++i)
		b[i][nod] = b[i - 1][b[i - 1][nod]];
	
	forit(it, fiu[nod])
	{
		if (*it == nod) continue;
		
		lvl[*it] = lvl[nod] + 1;
		df(*it);
	}
}

int lca(int x, int y)
{
	if (lvl[x] > lvl[y])
		x ^= y ^= x ^= y;
	
	while (lvl[y] > lvl[x])
		y = b[lg(lsb(lvl[y] - lvl[x]))][y];
	
	if (x == y) return x;
	
	for (int step = pow - 1; step; --step)
		if (b[step][x] != b[step][y])
			x = b[step][x], y = b[step][y];
		
	return b[1][x];
}

int main()
{
	int i, j, x, x1, x2, y1, y2;

	freopen("matrice2.in", "r", stdin);
	freopen("matrice2.out", "w", stdout);

	scanf("%d %d", &n, &m);

	dir[0] = -n;
	dir[1] = 1;
	dir[2] = n;
	dir[3]= -1;

	for (i = 0; i < n; ++i)
		for (j = 0; j < n; ++j)
		{
			scanf("%d", &x);
			v.pb( mp(-x, i * n + j) );
		}

	sort(v.begin(), v.end());
	
	forit(it, v)
	{
		it->x *= -1;
		val[it->y] = it->x;
	}

	build_tree();

	for (i = 0; i < n * n; ++i)
	{
		fiu[t[i]].pb(i);
		if (i == t[i]) root = i;
	}
	
	memset(f, 0, sizeof(f));
	lvl[root] = 0;
	df(root);
	
	for (i = 1; i <= m; ++i)
	{
		scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
		--x1; --x2; --y1; --y2;
		
		//printf("lca: %d\n", lca(x1 * n + y1, x2 * n + y2));
		printf("%d\n", val[lca(x1 * n + y1, x2 * n + y2)]);
	}
}