Pagini recente » Judete | Cod sursa (job #1574600) | Cod sursa (job #3121009) | Cod sursa (job #1165839) | Cod sursa (job #798718)
Cod sursa(job #798718)
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#define NLen 0x200
#define QLen 0x8000
#define NumLen 0x100000
using namespace std;
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
int Mat[NLen][NLen];
char frq[NumLen];
int use[NumLen];
int G[NLen*NLen];
int aux[QLen];
int Sol[QLen];
int N;
int Q;
int last;
struct Point
{
int sx,sy,fx,fy;
}P[QLen];
struct Position
{
int value,idx;
}v[NLen*NLen],h[QLen];
inline bool Comp_v(const Position &a,const Position &b)
{
return a.value<b.value;
}
inline bool Comp_h(const Position &a,const Position &b)
{
return a.value>b.value;
}
inline int Convert(int a,int b)
{
return (a-1)*N+b;
}
inline int root(int nod)
{
if(G[nod]!=nod) G[nod]=root(G[nod]);
return G[nod];
}
inline void unite(int x,int y)
{
G[root(x)]=root(y);
}
inline void grow(int H)
{
//fiecare element care nu a fost deja pus in graf il unesc cu padurile din jur
int i;
for(i=last;i>0&&v[i].value>=H;--i)
{
int x=v[i].idx/N;
int y=v[i].idx%N;
if(y==0) y=N;
else ++x;
for(int j=0;j<4;++j)
if(0<x+dx[j]&&x+dx[j]<=N&&
0<y+dy[j]&&y+dy[j]<=N&&
Mat[x+dx[j]][y+dy[j]]>=H)
{
unite(v[i].idx,Convert(x+dx[j],y+dy[j]));
}
}
last=i;
}
int main()
{
freopen("matrice2.in","r",stdin);
freopen("matrice2.out","w",stdout);
cin>>N>>Q;
for(int i=1;i<=N;++i)
for(int j=1;j<=N;++j)
cin>>Mat[i][j];
for(int i=1;i<=Q;++i)
cin>>P[i].sx>>P[i].sy>>P[i].fx>>P[i].fy;
//folosesc un vector de frecventa pe care il restrans (elimin 0-urile)
for(int i=1;i<=N;++i)
for(int j=1;j<=N;++j)
frq[Mat[i][j]]=1;
int M=0;
for(int i=1;i<NumLen;++i)
if(frq[i]) use[++M]=i;
//transform matricea in vector
//sortez elementele vectorului
int L=0;
for(int i=1;i<=N;++i)
for(int j=1;j<=N;++j)
{
v[++L].value=Mat[i][j];
v[L].idx=L;
}
sort(v+1,v+L+1,Comp_v);
//fac cautarile binare smechere in paralel
//construiesc graful pe parcurs, caut binar query-urile care au un h mai mare
//h = pozitia inaltimii in use
//use = valuarea efectiva a inaltimii
memset(h,0,sizeof(h));
for(int i=1;i<=Q;++i) h[i].idx=i;
int step;
for(step=1;step<M;step*=2);
for(;step;step/=2)
{
//resetez graful G
for(int i=1;i<=L;++i) G[i]=i;
//last e pozitia primului element pe care il pun in padure
//in functia grow
last=L;
//sortez h (inaltimile minime care trebuie sa fie pe drum) in ordine descrescatoare,
//ca sa pot sa extind graful
sort(h+1,h+Q+1,Comp_h);
//folosesc un vector auxiliar deoarece am nevoie de h-urile vechi pentru a imi da seama cand extind G
for(int i=1;i<=Q;++i) aux[i]=h[i].value;
for(int i=1;i<=Q;++i)
if(h[i].value+step<=M) //conditie pentru BS
{
//daca graful nu este setat (i=1) sau daca s-a schimbat h-ul, fac update
if(i==1||h[i].value!=h[i-1].value) grow(use[h[i].value+step]);
//verific daca (sx,sy) si (fx,fy) se alfa in aceeasi padure
int ind=h[i].idx;
int sx=P[ind].sx;
int sy=P[ind].sy;
int fx=P[ind].fx;
int fy=P[ind].fy;
int r_s=root(Convert(sx,sy));
int r_f=root(Convert(fx,fy));
if(r_s==r_f) aux[i]=h[i].value+step;
}
//actualizez h (vector de pozitii)
for(int i=1;i<=Q;++i) h[i].value=aux[i];
}
//Solutie
for(int i=1;i<=Q;++i)
Sol[h[i].idx]=use[h[i].value];
for(int i=1;i<=Q;++i) cout<<Sol[i]<<'\n';
return 0;
}