Cod sursa(job #309658)

Utilizator Mishu91Andrei Misarca Mishu91 Data 30 aprilie 2009 21:00:35
Problema Matrice 2 Scor Ascuns
Compilator cpp Status done
Runda Marime 2.45 kb
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

#define NMAX 310
#define NMAX2 91000
#define LGMAX 20

#define MP make_pair
#define ff first
#define ss second

int N, M, lgmax;

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

vector <int> leg[NMAX2];

int a[NMAX][NMAX];
int pz[NMAX][NMAX];

pair <int, pair<int, int> > b[NMAX2];

int val[NMAX2];
int tata[LGMAX][NMAX2];
int tt[NMAX2];
int niv[NMAX2];

int father(int x)
{
	if (tt[x] == x) return x;
	return tt[x] = father(tt[x]);
}

void unite(int x, int y)
{
	if (val[x] > val[y]) tata[0][x] = y, leg[y].push_back(x), tt[x] = y;
	else tata[0][y] = x, leg[x].push_back(y), tt[y] = x;
}

void back(int x)
{
	for (vector <int> :: iterator it = leg[x].begin(); it != leg[x].end(); ++it) {
		niv[*it] = niv[x] + 1;
		back(*it);
	}
}

int lca(int x, int y)
{
	int k;

	for (k = lgmax; k >= 0 && niv[x] > niv[y]; k--)
		if (niv[ tata[k][x] ] >= niv[y])
			x = tata[k][x];
	for (k = lgmax; k >= 0 && niv[y] > niv[x]; k--)
		if (niv[ tata[k][y] ] >= niv[x])
			y = tata[k][y];

	for (k = lgmax; k >= 0 && x != y; k--)
		if (tata[k][x] != tata[k][y])
			x = tata[k][x], y = tata[k][y];

	if (x == y) return x;
	return tata[0][x];
}

int main()
{
	int i, j, x, y, xx, yy, dir, k, nb = 0;

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

	scanf("%d %d", &N, &M);

	for (i = 1; i <= N; i++) {
		for (j = 1; j <= N; j++) {
			scanf("%d", &a[i][j]);

			b[++nb].ff = a[i][j];
			b[nb].ss = MP(i, j);
		}
	}

	int N2 = N * N;

	sort(b + 1, b + N2 + 1);
	reverse(b + 1, b + N2 + 1);

	for (i = 1; i <= N2; i++) {
		x = b[i].ss.ff; y = b[i].ss.ss;

//		printf("%d %d\n", x, y);

		tata[0][i] = i;
		val[i] = b[i].ff;
		pz[x][y] = i;
		tt[i] = i;

		for (dir = 0; dir < 4; dir++) {
			xx = x + dx[dir]; yy = y + dy[dir];
			if (!(1 <= xx && xx <= N && 1 <= yy && yy <= N)) continue;
			if (!pz[xx][yy]) continue;

			int q = father(i), w = father(pz[xx][yy]);
			
//			printf("%d %d - %d %d | %d %d\n", x, y, xx, yy, q, w);

			if (q == w) continue;
			unite(q, w);
		}
	}


	for (i = 1; i <= N2; i++) if (tata[0][i] == i) back(i);

	for (k = 1; (1 << (k - 1)) <= N2; k++) 
		for (i = 1; i <= N2; i++) tata[k][i] = tata[k - 1][tata[k - 1][i]];

//	printf("\n");
//	for (i = 1; i <= N2; i++) printf("%d %d\n", i, tata[0][i]);

	lgmax = k - 1;

	for (i = 1; i <= M; i++) {
		scanf("%d %d %d %d", &x, &y, &xx, &yy);

		x = pz[x][y]; y = pz[xx][yy];

		int q = lca(x, y);

		printf("%d\n", val[q]);
	}

return 0;
}