Cod sursa(job #1018027)

Utilizator alex_unixPetenchea Alexandru alex_unix Data 28 octombrie 2013 19:59:57
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.38 kb

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <utility>

const int MAX_N(305);
const int MAX_Q(20005);

int n, q;
int Matrix [MAX_N] [MAX_N];
int Forest [MAX_N * MAX_N];
int Temp [MAX_N] [MAX_N];
std::pair<int,int> Index [MAX_N * MAX_N];
std::pair<int,int> v [MAX_N * MAX_N];

struct Q
{
	int a;
	int b;
	int c;
	int r;
} Query [MAX_Q];

void Read (void)
{
	std::freopen("matrice2.in","r",stdin);
	std::scanf("%d %d",&n,&q);
	int i, j, k;
	for (i = k = 1 ; i <= n ; ++i)
		for (j = 1 ; j <= n ; ++j)
		{
			std::scanf("%d",&Matrix[i][j]);
			Temp[i][j] = k;
			Index[k] = std::make_pair(i,j);
			v[k] = std::make_pair(-Matrix[i][j],k);
			++k;
		}
	for (i = 1 ; i <= q ; ++i)
	{
		std::scanf("%d %d",&j,&k);
		Query[i].a = Temp[j][k];
		std::scanf("%d %d",&j,&k);
		Query[i].b = Temp[j][k];
		Query[i].c = i;
	}
	std::fclose(stdin);
}

inline void Print (void)
{
	std::freopen("matrice2.out","w",stdout);
	std::sort(Query + 1,Query + q + 1,[ ] (Q x, Q y) {return x.c < y.c;});
	for (int i(1) ; i <= q ; ++i)
		std::printf("%d\n",Query[i].r);
	std::fclose(stdout);
}

int ForestFind (int node)
{
	if (Forest[node] == 0)
		return 0;
	if (Forest[node] < 0)
		return node;
	return Forest[node] = ForestFind(Forest[node]);
}

inline void ForestMerge (int x, int y)
{
	x = ForestFind(x);
	y = ForestFind(y);
	if (x == y)
		return;
	if (Forest[x] < Forest[y])
		std::swap(x,y);
	Forest[y] += Forest[x];
	Forest[x] = y;
}

void ForestInsert (int node)
{
	static const int WAY(4);
	static const int X [ ] = {1,-1,0,0};
	static const int Y [ ] = {0,0,-1,1};
	Forest[node] = -1;
	for (int k(0) ; k < WAY ; ++k)
		if (Forest[Temp[Index[node].first + X[k]][Index[node].second + Y[k]]])
			ForestMerge(node,Temp[Index[node].first + X[k]][Index[node].second + Y[k]]);
}

inline void Compute (void)
{
	const int END(n * n);
	int step, i, j;
	std::sort(v + 1,v + END + 1);
	for (i = 1 ; i <= END ; ++i)
		v[i].first = -v[i].first;
	for (step = 1 << 30 ; step ; step >>= 1)
	{
		std::memset(Forest,0,sizeof(Forest));
		std::sort(Query + 1,Query + q + 1,[ ] (Q x, Q y) {return x.r > y.r;});
		for (i = 1, j = 1 ; j <= q ; ++j)
		{
			while (i <= END && Query[j].r + step <= v[i].first)
			{
				ForestInsert(v[i].second);
				++i;
			}
			if (Forest[Query[j].a] && Forest[Query[j].b] && ForestFind(Query[j].a) == ForestFind(Query[j].b))
				Query[j].r += step;
		}
	}
}

int main (void)
{
	Read();
	Compute();
	Print();
	return 0;
}