Cod sursa(job #321702)

Utilizator tvladTataranu Vlad tvlad Data 6 iunie 2009 22:24:14
Problema Matrice 2 Scor 85
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.31 kb
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

struct pozitie {
	int val, x,y;
	pozitie ( int V, int X, int Y ) { val = V; x = X; y = Y; }
};
bool operator< ( const pozitie &a, const pozitie &b ) { return a.val > b.val; };

const int N_MAX = 300;
const int TOT = N_MAX*N_MAX+1;
const int logTOT = 17;
const int ND = 4;
const pozitie D[ND] = { pozitie(0,1,0), pozitie(0,0,1), pozitie(0,-1,0), pozitie(0,0,-1) };
const int INF = 0x3f3f3f3f;

int n,q;
int a[N_MAX][N_MAX];

vector<pozitie> v;
int used[N_MAX][N_MAX];
int tata[TOT], cost[TOT], h[TOT];

int root;
vector< pair<int,int> > G[TOT];
int level[TOT], anc[TOT][logTOT];
bool useddf[TOT];

int component ( int k ) {
	if (tata[k] == k)
		return k; else
		return component(tata[k]);
}

void join ( int c1, int c2, int val ) {
	if (h[c1] < h[c2])
		c1 ^= c2 ^= c1 ^= c2;
	tata[c2] = c1;
	cost[c2] = val;
	if (h[c1] < h[c2]+1)
		h[c1] = h[c2]+1;
}

void get_component_tree() {
	sort(v.begin(),v.end());
	for (vector<pozitie>::iterator cur = v.begin(); cur != v.end(); ++cur) {
		used[cur->x][cur->y] = cur - v.begin() + 1;
		tata[used[cur->x][cur->y]] = used[cur->x][cur->y];
		h[used[cur->x][cur->y]] = 1;
		for (int i = 0; i < ND; ++i) {
			int x = cur->x + D[i].x;
			int y = cur->y + D[i].y;
			int c1,c2;
			if (0 <= x && x < n && 0 <= y && y < n && used[x][y] && (c1 = component(used[x][y])) != (c2 = component(used[cur->x][cur->y]))) {
				join(c1, c2, cur->val);
			}
		}
	}
}

void ancestors_df ( int k ) {
	useddf[k] = true;
	anc[k][0] = tata[k];
	for (int i = 1; i < logTOT; ++i)
		anc[k][i] = anc[anc[k][i-1]][i-1];
	for (vector< pair<int,int> >::iterator next = G[k].begin(); next != G[k].end(); ++next) {
		if (!useddf[next->first]) {
			level[next->first] = level[k] + 1;
			ancestors_df(next->first);
		}
	}
}

void get_ancestors() {
	for (int i = 1; i <= n*n; ++i)
		if (tata[i] == i)
			root = i; else
			G[tata[i]].push_back(make_pair(i,cost[i]));
	ancestors_df(root);
	for (int i = 1; i <= n*n; ++i)
		if (!useddf[i])
			for(;;);
}

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

int lca ( int a, int b ) {
	if (level[a] > level[b]) {
		a ^= b ^= a ^= b;
	}
	while (level[b] - level[a]) {
		//fprintf(stderr,"lsb(%d) = %d\n",level[b]-level[a],lsb(level[b]-level[a]));
		b = anc[b][log(lsb(level[b]-level[a]))];
	}
	for (int step = logTOT-1; step >= 0; --step) {
		if (anc[a][step] != anc[b][step]) {
			a = anc[a][step];
			b = anc[b][step];
		}
	}
	a = anc[a][0];
	b = anc[b][0];
	return a;
}

int main() {
	freopen("matrice2.in","rt",stdin);
	freopen("matrice2.out","wt",stdout);
	scanf("%d %d",&n,&q);
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			scanf("%d",&a[i][j]);
			v.push_back(pozitie(a[i][j],i,j));
		}
	}
	get_component_tree();
	get_ancestors();
	for (int i = 0, a,b,c,d; i < q; ++i) {
		scanf("%d %d %d %d",&a,&b,&c,&d);
		--a; --b; --c; --d;
		int v1 = used[a][b], v2 = used[c][d];
		int x = lca(v1,v2);
		int min = INF;
		for (int cur = v1; cur != x; cur = tata[cur])
			if (min > cost[cur])
				min = cost[cur];
		for (int cur = v2; cur != x; cur = tata[cur])
			if (min > cost[cur])
				min = cost[cur];
		printf("%d\n",min);
	}
	return 0;
}