Cod sursa(job #1068630)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 28 decembrie 2013 15:47:45
Problema Struti Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.33 kb
#include <iostream>
#include <fstream>
#include <deque>

using namespace std;

const int Nmax = 1001;

struct DEQUE
{
    int frnt;
    int bck;
    int d[Nmax];

    void clear()
    {
        frnt = 1;
        bck = 0;
    }

    int size()
    {
        if ( frnt <= bck )
                return bck - frnt + 1;
        else
                return 0;
    }

    int back()
    {
        return d[ bck ];
    }

    int front()
    {
        return d[ frnt ];
    }

    void pop_back()
    {
        bck--;
    }

    void pop_front()
    {
        frnt++;
    }

    void push_back( int value )
    {
        d[ ++bck ] = value;
    }
};

int N, M, P, answer, counts;
int A[Nmax][Nmax];

DEQUE min_col[Nmax];
DEQUE max_col[Nmax];
DEQUE min_lin, max_lin;


void query( int dx, int dy )
{
    for ( int i = 1; i <= M; ++i )
    {
        min_col[i].clear();
        max_col[i].clear();
    }

    for ( int i = 1; i <= N; ++i )
    {
        min_lin.clear();
        max_lin.clear();

        for ( int j = 1; j <= M; ++j )
        {
            /// minimul de pe coloana j
            while ( min_col[j].size() && A[ min_col[j].back() ][j] >= A[i][j] ) min_col[j].pop_back();
            while ( min_col[j].size() && min_col[j].front() <= i - dx ) min_col[j].pop_front();

            min_col[j].push_back ( i );

            /// maximul de pe coloana j
            while ( max_col[j].size() && A[ max_col[j].back() ][j] <= A[i][j] ) max_col[j].pop_back();
            while ( max_col[j].size() && max_col[j].front() <= i - dx ) max_col[j].pop_front();

            max_col[j].push_back( i );

            if ( i >= dx )
            {
                int min_i = min_col[j].front();
                int max_i = max_col[j].front();

                /// minimul din dreptunghiul [i,j]->[i+dx-1,j+dy-1]
                while ( min_lin.size() && A[ min_col[ min_lin.back() ].front() ][ min_lin.back() ] >= A[ min_i ][j] ) min_lin.pop_back();
                while ( min_lin.size() && min_lin.front() <= j - dy ) min_lin.pop_front();

                min_lin.push_back( j );

                /// maximul din dreptunghiul [i,j]->[i+dx-1,j+dy-1]
                while ( max_lin.size() && A[ max_col[ max_lin.back() ].front() ][ max_lin.back() ] <= A[ max_i ][j] ) max_lin.pop_back();
                while ( max_lin.size() && max_lin.front() <= j - dy ) max_lin.pop_front();

                max_lin.push_back( j );

                if ( j >= dy )
                {
                    int min_l, max_l, min_c, max_c;

                    min_c = min_lin.front();
                    max_c = max_lin.front();

                    min_l = min_col[ min_c ].front();
                    max_l = max_col[ max_c ].front();

                    int diff = A[ max_l ][ max_c ] - A[ min_l ][ min_c ];

                    if ( diff < answer )
                    {
                        answer = diff;
                        counts = 1;
                    }
                    else
                    {
                        if ( diff == answer )
                        {
                            counts++;
                        }
                    }
                }
            }
        }

    }
}


const int DIM_BUFF = ( 1 << 23 );

char buffer[DIM_BUFF];
int position = DIM_BUFF;

char GetChar()
{
    if ( position == DIM_BUFF )
    {
        fread( buffer, 1, DIM_BUFF, stdin );
        position = 0;
    }

    return buffer[ position++ ];
}

int rd()
{
    int nr = 0;
    char c;

    do
    {
        c = GetChar();

    } while ( !isdigit( c ) );

    do
    {
        nr = nr * 10 + ( c - '0' );
        c = GetChar();

    } while ( isdigit( c ) );

    return nr;
}

int main()
{
    freopen("struti.in", "r", stdin);
    freopen("struti.out", "w", stdout);

    N = rd(); M = rd(); P = rd();

    for ( int i = 1; i <= N; ++i )
    {
        for ( int j = 1; j <= M; ++j )
        {
            A[i][j] = rd();
        }
    }

    for ( int i = 1, dx, dy; i <= P; ++i )
    {
        answer = 10000;
        counts = 0;

        dx = rd(); dy = rd();

        query( dx, dy );

        if ( dx != dy )
                query( dy, dx );

       printf("%d %d\n", answer, counts);
    }

    return 0;
}