Cod sursa(job #1727199)

Utilizator StarGold2Emanuel Nrx StarGold2 Data 10 iulie 2016 01:05:58
Problema Matrice 2 Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.74 kb
#include <cstdio>
#include <vector>
#include <algorithm>

struct Query {

    int X1, Y1, X2, Y2;
    int Answer, Index;

    Query() {}
    Query( int X1, int Y1, int X2, int Y2, int Answer, int Index ) {
        this -> X1 = X1; this -> Y1 = Y1;
        this -> X2 = X2; this -> Y2 = Y2;
        this -> Answer = Answer;
        this -> Index = Index;
    }
}; std::vector <Query> MyQuerys;

struct Element {

    int Value, X, Y;

    Element() {}
    Element( int Value, int X, int Y ) {
        this -> Value = Value;
        this -> X = X; this -> Y = Y;
    }
}; std::vector <Element> MyElements;

std::vector <int> DisjointSet;
std::vector < std::vector <int> > Matrix;

int Dx[4] = { -1, 0, 1, 0 };
int Dy[4] = { 0, 1, 0, -1 };

inline bool comp1( Element MyElement1, Element MyElement2 ) {
    return MyElement1.Value > MyElement2.Value;
}

inline bool comp2( Query MyQuery1, Query MyQuery2 ) {
    return MyQuery1.Answer > MyQuery2.Answer;
}

inline bool comp3( Query MyQuery1, Query MyQuery2 ) {
    return MyQuery1.Index < MyQuery2.Index;
}

inline int root( int Pos ) {
    return ( DisjointSet[Pos] < 0 ) ? Pos : root( DisjointSet[Pos] );
}

void SolveTestCase( void ) {
    int N, Q, X1, Y1, X2, Y2, X, Y;

    scanf( "%d %d", &N, &Q );

    MyElements.clear(); MyQuerys.clear();
    DisjointSet.resize( N * N );
    Matrix.resize( N );

    for( int i = 0; i < N; i ++ ) {
        Matrix[i].resize( N );

        for( int j = 0; j < N; j ++ ) {
            scanf( "%d", &Matrix[i][j] );
            MyElements.push_back( {Matrix[i][j], i, j} );
        }
    }

    for( int i = 0; i < Q; i ++ ) {
        scanf( "%d %d %d %d", &X1, &Y1, &X2, &Y2 );
        MyQuerys.push_back( {X1 - 1, Y1 - 1, X2 - 1, Y2 - 1, 0, i} );
    }

    for( int k = (1 << 20); k; k /= 2 ) {
        std::sort( MyElements.begin(), MyElements.end(), comp1 );
        std::sort( MyQuerys.begin(), MyQuerys.end(), comp2 );
        std::fill( DisjointSet.begin(), DisjointSet.end(), -1 );

        int Cursor = 0;
        for( int i = 0; i < MyElements.size(); i ++ ) {
            X = MyElements[i].X; Y = MyElements[i].Y;

            for( int d = 0; d < 4; d ++ ) {
                int X1 = X + Dx[d], Y1 = Y + Dy[d];

                if( X1 < 0 || X1 >= N ) continue;
                if( Y1 < 0 || Y1 >= N ) continue;
                if( Matrix[X1][Y1] < Matrix[X][Y] ) continue;

                int Pos1 = root( X * N + Y ), Pos2 = root( X1 * N + Y1 );

                if( Pos1 != Pos2 ) {
                    if( DisjointSet[Pos1] < DisjointSet[Pos2] ) {

                        DisjointSet[Pos1] += DisjointSet[Pos2];
                        DisjointSet[Pos2] = Pos1;
                    } else {

                        DisjointSet[Pos2] += DisjointSet[Pos1];
                        DisjointSet[Pos1] = Pos2;
                    }
                }
            }

            if( i < MyElements.size() && Cursor < MyQuerys.size() && MyElements[i + 1].Value >= MyQuerys[Cursor].Answer + k )
                continue;

            while( Cursor < MyQuerys.size() && MyElements[i].Value <= MyQuerys[Cursor].Answer + k ) {
                int Pos1 = root( MyQuerys[Cursor].X1 * N + MyQuerys[Cursor].Y1 );
                int Pos2 = root( MyQuerys[Cursor].X2 * N + MyQuerys[Cursor].Y2 );

                if( Pos1 == Pos2 )
                    MyQuerys[Cursor].Answer += k;

                Cursor ++;
            }
        }
    }

    std::sort( MyQuerys.begin(), MyQuerys.end(), comp3 );

    for( int i = 0; i < MyQuerys.size(); i ++ )
        printf( "%d\n", MyQuerys[i].Answer );

    return;
}

int main( int argc, const char *argv[] ) {
    int T = 1;

    freopen( "matrice2.in" , "r", stdin  );
    freopen( "matrice2.out", "w", stdout );

    for( int i = 1; i <= T; i ++ )
        SolveTestCase();

    return 0;
}