Cod sursa(job #654079)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 29 decembrie 2011 15:38:56
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.97 kb
#include<stdio.h>
#include<algorithm>

#define maxn 305
#define maxq 20005

using namespace std;

FILE*f=fopen("matrice2.in","r");
FILE*g=fopen("matrice2.out","w");

int n,q,i,j,val_max,x1,y1,x2,y2,puncte,iv,jv,d,viz[maxn][maxn];
int A[maxn][maxn],sol[maxq],T[maxn*maxn],rg[maxn*maxn];

int di[] = {-1,0,1,0};
int dj[] = {0,1,0,-1};

inline int point ( int x , int y ){
	int p = (x-1)*n + y;
	return p;
}

struct _query{
	_query(int p1 = 0,int p2 = 0,int p = 0,int u = 0,int ind = 0):p1(p1),p2(p2),p(p),u(u),ind(ind){}
	
	int p1,p2;
	int p,u;
	int ind;
	
	friend bool operator < ( const _query &a , const _query &b ){
		return ((a.p+a.u)>>1) < ((b.p+b.u)>>1);
	}
}Q[maxq];

struct _punct{
	_punct(int x = 0,int y = 0):x(x),y(y){}
	
	int x,y;
	
	friend bool operator < ( const _punct &a , const _punct &b ){
		return A[a.x][a.y] < A[b.x][b.y];
	}		
}P[maxn*maxn];

inline void citire () {
	
	fscanf(f,"%d %d",&n,&q);
	
	for ( i = 1 ; i <= n ; ++i ){
		for ( j = 1 ; j <= n ; ++j ){
			fscanf(f,"%d",&A[i][j]);
			val_max = max(val_max,A[i][j]);
			P[++puncte] = _punct(i,j);
		}
	}
	
	for ( i = 1 ; i <= q ; ++i ){
		fscanf(f,"%d %d %d %d",&x1,&y1,&x2,&y2);
		Q[i] = _query(point(x1,y1),point(x2,y2),1,val_max,i);
	}
}

inline void unify ( int r1 , int r2 ){
	
	if ( rg[r1] > rg[r2] ){
		T[r2] = r1;
	}
	else{
		T[r1] = r2;
	}
	
	if ( rg[r1] == rg[r2] ){
		++rg[r2];
	}
}

inline int root ( int x ){
	int r;
	
	for ( r = x ; T[r] != r ; r = T[r] );
	
	while ( T[x] != x ){
		int aux = T[x];
		T[x] = r;
		x = aux;
	}
	
	return r;
}

inline void solve () {
	int finished = 0, p;
	
	sort(P+1,P+puncte+1);
	
	do{
		sort(Q+1,Q+q+1); finished = 1; p = q + 1;
		
		for ( i = 1 ; i <= puncte ; ++i ){
			T[i] = i; rg[i] = 1;
		}
		
		for ( i = 1 ; i <= n ; ++i ){
			for ( j = 1 ; j <= n ; ++j ){
				viz[i][j] = 0;
			}
		}
		
		for ( i = puncte ; i >= 0 ; --i ){
			
			if ( A[P[i].x][P[i].y] != A[P[i+1].x][P[i+1].y] && A[P[i+1].x][P[i+1].y] ){
				
				while ( ((Q[p-1].p+Q[p-1].u)>>1) > A[P[i].x][P[i].y] && p ){
					
					--p;
					
					if ( !Q[p].ind )	continue ;
					
					if ( root(Q[p].p1) == root(Q[p].p2) ){
						Q[p].p = ((Q[p].p+Q[p].u)>>1) + 1;
					}
					else{
						Q[p].u = ((Q[p].p+Q[p].u)>>1) - 1;
					}
					
					if ( Q[p].p <= Q[p].u ){
						finished = 0;
					}
					else{
						sol[Q[p].ind] = Q[p].u;
						Q[p].ind = 0;
					}
				}
			}				
			
			viz[P[i].x][P[i].y] = 1;
			for ( d = 0 ; d < 4 ; ++d ){
				iv = P[i].x + di[d]; jv = P[i].y + dj[d];
				
				if ( iv >= 1 && iv <= n && jv >= 1 && jv <= n && viz[iv][jv] ){
					int r1 = root(point(P[i].x,P[i].y));
					int r2 = root(point(iv,jv));
					
					if ( r1 != r2 ){
						unify(r1,r2);
					}
				}
			}
		}			
		
		
	}while(!finished);
	
	for ( i = 1 ; i <= q ; ++i ){
		fprintf(g,"%d\n",sol[i]);
	}
}

int main () {
	
	citire();
	
	solve();
	
	fclose(f);
	fclose(g);
	
	return 0;
}