Cod sursa(job #1529205)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 20 noiembrie 2015 16:51:34
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.69 kb
#include<cstdio>
#include<algorithm>
#include<vector>

using namespace std;

FILE *fin = fopen( "matrice2.in", "r" ), *fout = fopen( "matrice2.out", "w" );

const int nmax = 310;
const int qmax = 20000;
const int valmax = 1e6;
const int inf = 1 << 30;
const int dl[ 4 ] = { -1, 0, 0, 1 };
const int dc[ 4 ] = { 0, -1, 1, 0 };
int n, nrq;
int v[ nmax * nmax + 1 ];
int tata[ nmax * nmax + 1 ], grad[ nmax * nmax + 1 ];
int ans[ qmax + 1 ];

vector< int > g[ nmax * nmax + 1 ];

struct keke{
    int nr, val;

    keke() {}
    keke( int _nr, int _val ) {
        nr = _nr, val = _val;
    }
    inline bool operator < ( const keke &a ) const {
        return ( val > a.val );
    }
};
vector< keke > s;

struct query{
    int a, b;
} q[ qmax + 1 ];

struct check_query{
    int ind, val;
    bool ans;

    inline bool operator < ( const check_query &x ) const {
        return ( val > x.val );
    }
} c[ qmax + 1 ];

inline int nr_asociat( int x, int y ) {
    return (x - 1) * (n + 3) + y;
}
int find_tata( int x ) {
    if ( x == tata[ x ] ) {
        return x;
    }
    return ( tata[ x ] = find_tata( tata[ x ] ) );
}
void uneste( int x, int y ) {
    int ta = find_tata( x ), tb = find_tata( y );
    if ( ta == tb )
        return ;
    if ( grad[ ta ] < grad[ tb ] ) {
        grad[ tb ] += grad[ ta ];
        tata[ ta ] = tb;
    } else {
        grad[ ta ] += grad[ tb ];
        tata[ tb ] = ta;
    }
}
void unifica( int x, int val ) {
    for( vector< int >::iterator it = g[ x ].begin(); it != g[ x ].end(); ++ it ) {
        if ( v[ *it ] >= val ) {
            uneste( x, *it );
        }
    }
}
void verif_tot() {
    for( int i = 1; i <= n; ++ i ) {
        for( int j = 1; j <= n; ++ j ) {
            int x = nr_asociat( i, j );
            tata[ x ] = x;
            grad[ x ] = 1;
        }
    }

    sort( c, c + nrq );
    int j = 0;
    for( int i = 0; i < nrq; ++ i ) {
        while ( j < n * n && s[ j ].val >= c[ i ].val ) {
            unifica( s[ j ].nr, c[ i ].val );
            ++ j;
        }
        int ta, tb;
        ta = find_tata( q[ c[ i ].ind ].a );
        tb = find_tata( q[ c[ i ].ind ].b );

        c[ i ].ans = (ta == tb);
    }
}
void cautare_binara_in_paralel() {
    int n2;
    for( n2 = 1; (n2 << 1) <= valmax; n2 <<= 1 ) {
    }

    for( int step = n2; step > 0; step >>= 1 ) {
        for( int i = 0; i < nrq; ++ i ) {
            c[ i ].ind = i;
            if ( ans[ i ] + step > valmax ) {
                c[ i ].val = ans[ i ];
            } else {
                c[ i ].val = ans[ i ] + step;
            }
        }
        verif_tot();

        for( int i = 0; i < nrq; ++ i ) {
            if ( c[ i ].ans == 1 ) {
                ans[ c[ i ].ind ] = c[ i ].val;
            }
        }
    }
}
int main() {
    fscanf( fin, "%d%d", &n, &nrq );
    for( int i = 1; i <= n; ++ i ) {
        for( int j = 1; j <= n; ++ j ) {
            int x = nr_asociat( i, j );

            fscanf( fin, "%d", &v[ x ] );
            s.push_back( keke( x, v[ x ] ) );

            for( int k = 0; k < 4; ++ k ) {
                g[ x ].push_back( nr_asociat( i + dl[ k ], j + dc[ k ] ) );
            }
        }
    }
    for( int i = 0; i < nrq; ++ i ) {
        int x1, y1, x2, y2;
        fscanf( fin, "%d%d%d%d", &x1, &y1, &x2, &y2 );
        q[ i ].a = nr_asociat( x1, y1 );
        q[ i ].b = nr_asociat( x2, y2 );
    }

    for( int i = 0; i <= n + 1; ++ i ) {
        v[ nr_asociat( i, 0 ) ] = v[ nr_asociat( 0, i ) ] = -inf;
        v[ nr_asociat( i, n + 1 ) ] = v[ nr_asociat( n + 1, i ) ] = -inf;
    }
    sort( s.begin(), s.end() );
    cautare_binara_in_paralel();

    for( int i = 0; i < nrq; ++ i ) {
        fprintf( fout, "%d\n", ans[ i ] );
    }
    fclose( fin );
    fclose( fout );
    return 0;
}