Cod sursa(job #993749)

Utilizator mitrutstrutMitrea Andrei Ionut mitrutstrut Data 4 septembrie 2013 13:18:32
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.62 kb
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;
 
#define QM 20010
#define NM 310
 
struct Data
{
    int Val, L, C;
}V[NM * NM];
 
struct Query
{
    int Pos, Ans;
    int X1, Y1, X2, Y2;
}Q[QM];
 
 
int N, M, K, A[NM][NM], Mat[NM][NM], Ans[QM], Father[NM * NM];
int DX[4] = {-1, 0, 0, 1}, DY[4] = {0, -1, 1, 0};
 
struct CompData
{
    bool operator() (const Data &A, const Data &B) const
    {
        return A.Val > B.Val;
    }
};
 
struct CompQuery
{
    bool operator() (const Query &A, const Query &B) const
    {
        return A.Ans > B.Ans;
    }
};
 
int Root(int X)
{
    int Y, P = X;
    for(; P != Father[P]; P = Father[P]);
    while(X != P)
    {
        Y = Father[X];
        Father[X] = P;
        X = Y;
    }
    return P;
}
 
void Merge(int X, int Y)
{
    if(rand() % 2) Father[X] = Y;
    else Father[Y] = X;
}
 
bool OK(int X, int Y)
{
    return 1 <= X && X <= N && 1 <= Y && Y <= N;
}
 
void Add(int Idx, int Min)
{
    int L = V[Idx].L, C = V[Idx].C;
    for(int i = 0; i < 4; ++ i)
    {
        int NextL = L + DX[i], NextC = C + DY[i];
        if(OK(NextL, NextC) && A[NextL][NextC] >= Min)
            if(Root(Mat[L][C]) != Root(Mat[NextL][NextC]))
                Merge( Root(Mat[L][C]), Root(Mat[NextL][NextC]) );
    }
}
 
int main()
{
    freopen("matrice2.in", "r", stdin);
    freopen("matrice2.out", "w", stdout);
 
    scanf("%i %i", &N, &M);
    for(int i = 1; i <= N; ++ i)
        for(int j = 1; j <= N; ++ j)
        {
            scanf("%i", &A[i][j]);
            ++ K;
            V[K].L = i, V[K].C = j, V[K].Val = A[i][j];
            Mat[i][j] = K;
        }
    for(int i = 1; i <= M; ++ i)
    {
        scanf("%i %i %i %i", &Q[i].X1, &Q[i].Y1, &Q[i].X2, &Q[i].Y2);
        Q[i].Pos = i;
    }
 
    sort(V + 1, V + N * N + 1, CompData());
 
    int Step = int(log2(V[1].Val)) + 1;
 
    for(; Step >= 0; Step --)
    {
        sort(Q + 1, Q + M + 1, CompQuery());
        for(int i = 1; i <= N * N; ++ i) Father[i] = i;
 
        int j = 1;
        for(int i = 1; i <= M; ++ i)
        {
            int Now = Q[i].Ans + (1 << Step);
            for(; j <= N * N && V[j].Val >= Now; j ++)
                Add(j, Now);
 
            if(Root(Mat[ Q[i].X1 ][ Q[i].Y1 ]) == Root(Mat[ Q[i].X2 ][ Q[i].Y2 ]))
                Q[i].Ans += (1 << Step);
        }
    }
 
    for(int i = 1; i <= M; ++ i)
        Ans[ Q[i].Pos ] = Q[i].Ans;
 
    for(int i = 1; i <= M; ++ i)
        printf("%i\n", Ans[i]);
 
    return 0;
}