Cod sursa(job #869631)

Utilizator danalex97Dan H Alexandru danalex97 Data 1 februarie 2013 21:31:40
Problema Matrice 2 Scor 85
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.43 kb
#include <fstream>
#include <algorithm>
#include <set>
using namespace std;

ifstream F("matrice2.in");
ofstream G("matrice2.out");

const int Nmax = 305;
const int Qmax = 20010;

int N,M;

#define f first
#define s second

typedef struct
{
    int x;
    int y;
    int ord;
} q_type;

struct q_comp
{
    bool operator()(const q_type& a,const q_type& b)
    {
        return a.x < b.x || ( a.x == b.x && a.y < b.y );
    }
};

typedef struct
{
    int val;
    int key;
} v_type;

struct v_comp
{
    bool operator()(const v_type& a,const v_type& b)
    {
        return a.val > b.val ;
    }
};

q_type Q[Qmax];
v_type A[Nmax*Nmax];

set<int> Set[Nmax*Nmax];
// setul pointeaza la ordinea din query-urile sortate

int Mul[Nmax*Nmax];
int High[Nmax*Nmax];
int Ind[Nmax*Nmax];
// Ind pointeaza la Mul , Mul e varful multimii disjuncte
int Sol[Qmax],Val;

int Leg[Nmax*Nmax][4];

inline int make_nod( int i,int j )
{
    return (i-1) * N + j;
}

inline pair<int,int> get_nod(int val)
{
    int X = (val-1) / N;
    int Y = val - X * N;
    return make_pair( X , Y );
}

void Make_sets()
{
    for (int i=1;i<=2*M;++i)
    {
        F>> Q[i].x >> Q[i].y ;
        Q[i].ord = (i+1)/2;
        Ind[ make_nod( Q[i].x , Q[i].y ) ] = make_nod( Q[i].x , Q[i].y );
        Set[ Ind[ make_nod( Q[i].x , Q[i].y ) ] ].insert( Q[i].ord );
    }
}

bool Mark[Nmax*Nmax];

typedef set<int>::iterator ST;

void UniteSets(int N1,int N2) // unesc primul cu al 2-lea
{
    for (ST it=Set[N1].begin();it!=Set[N1].end();++it)
    {
        ST jt = Set[N2].find( *it );
        if ( jt != Set[N2].end() )
        {
            Sol[ *jt ] = Val;
            Set[N2].erase( *jt );
        }
        else
            Set[N2].insert( *it );
    }
    set<int>().swap( Set[N1] );
}

void Unite(int N1,int N2)
{
    if ( N1 == N2 )
        return;

    if ( Ind[N1] != Ind[N2] )
    {
        if ( Set[ Ind[N1] ].size() < Set[ Ind[N2] ].size() )
            UniteSets(Ind[N1],Ind[N2]), Ind[N1] = Ind[N2];
        else
            UniteSets(Ind[N2],Ind[N1]), Ind[N2] = Ind[N1];
    }

    if ( High[N1] == High[N2] )
    {
        Mul[ N1 ] = Mul[ N2 ];
        High[N2] ++;
    }
    else
    {
        if ( High[ N1 ] < High[ N2 ] )
            Mul[ N1 ] = Mul[ N2 ];
        else
            Mul[ N2 ] = Mul[ N1 ];
    }
}

inline int Go( int Nod )
{
    if ( Mul[ Nod ] == Nod ) return Nod;
    int Dad = Go( Mul[Nod] );
    Mul[Nod] = Dad;
    return Dad;
}

int main()
{
    F>>N>>M;
    for (int i=1;i<=N;++i)
        for (int j=1;j<=N;++j)
        {
            int nod = make_nod(i,j);
            F>>A[nod].val;

            A[nod].key = nod;
            Mul[nod] = nod;
            High[nod] = 1;

            if ( i > 1 ) Leg[nod][0] = make_nod(i-1,j);
            if ( j > 1 ) Leg[nod][1] = make_nod(i,j-1);
            if ( i < N ) Leg[nod][2] = make_nod(i+1,j);
            if ( j < N ) Leg[nod][3] = make_nod(i,j+1);
        }

    Make_sets();

   // sort(Q+1,Q+M+1,q_comp());
    sort(A+1,A+N*N+1,v_comp());

    for ( int i=1;i<=N*N;++i)
    {
        Val = A[i].val;
        Mark[ A[i].key ] = 1;
        for (int j=0;j<4;++j)
        {
            int to = Leg[A[i].key][j];
            if ( Mark [ to ] == 1 && to )
                Unite( Go( A[i].key ) , Go( to ) );
        }
    }

    for (int i=1;i<=M;++i)
        G<<Sol[i]<<'\n';
}