Cod sursa(job #898144)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 28 februarie 2013 06:58:22
Problema Struti Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.61 kb
#include <fstream>
#include <iostream>
#include <iterator>
#include <deque>
#include <limits>
#include <algorithm>
#include <cstring>
 
#define MAXN 1024
 
using namespace std;
 
short mat[MAXN][MAXN];
 
short matMin[MAXN][MAXN];
short matMax[MAXN][MAXN];
 
struct MinMaxDiff
{
    MinMaxDiff() :
        Diff(numeric_limits<short>::max()),
        Count(0)
    {}
     
    short Diff;
    int Count;
};
 
struct Entry
{
    Entry() :
        Value(0),
        Position(0)
    {}
     
    Entry(short v, short p) :
        Value(v),
        Position(p)
    {}
 
    short Value;
    short Position;
};
 
template <const int Rows, const int Columns, short (&Mat)[Rows][Columns]>
struct IterMat
{
    IterMat(short r, short c) :
        Row(r),
        Column(c)
    {}
 
    short& operator* ()
    {
        return Mat[Row][Column];
    }
     
    IterMat& operator++ ()
    {
        ++Row;
        return *this;
    }
 
private:
    short Row;
    short Column;
};
 
struct EntryValuesLess
{
    EntryValuesLess()
    {}
 
    inline bool operator () (const Entry lhs, short value) const
    {
        return lhs.Value <= value;
    }
};
 
struct EntryValuesGreater
{
    EntryValuesGreater()
    {}
 
    inline bool operator () (const Entry lhs, short value) const
    {
        return lhs.Value >= value;
    }
};
 
template <class Comparator>
inline static void PopBackElements(deque<Entry>& deq, short value)
{
    const Comparator comp;
    while (!deq.empty() && comp(deq.back(), value))
    {
        deq.pop_back();
    }
}
 
template<typename FirstIterType, typename SecondIterType>
static void GetMinMaxFromSequence(const short seq[], int n, int k, FirstIterType& itOutMin, SecondIterType& itOutMax)
{
    deque<Entry> deqMin;
    deque<Entry> deqMax;
 
    for (int i=0; i<k; ++i)
    {
        PopBackElements<EntryValuesGreater>(deqMin, seq[i]);
        deqMin.push_back(Entry(seq[i], i));
         
        PopBackElements<EntryValuesLess>(deqMax, seq[i]);
        deqMax.push_back(Entry(seq[i], i));
    }
     
    *itOutMin = deqMin.front().Value;
    ++itOutMin;
     
    *itOutMax = deqMax.front().Value;
    ++itOutMax;
     
    for (int i=k; i<n; ++i)
    {
        PopBackElements<EntryValuesGreater>(deqMin, seq[i]);
        deqMin.push_back(Entry(seq[i], i));
         
        if (deqMin.front().Position <= i-k)
        {
            deqMin.pop_front();
        }
         
        *itOutMin = deqMin.front().Value;
        ++itOutMin;
         
        PopBackElements<EntryValuesLess>(deqMax, seq[i]);
        deqMax.push_back(Entry(seq[i], i));
         
        if (deqMax.front().Position <= i-k)
        {
            deqMax.pop_front();
        }
         
        *itOutMax = deqMax.front().Value;
        ++itOutMax;
    }
}
 
static void PopulateMinMaxArray(int m, int n, int k)
{
    for (int i=0; i<m; ++i)
    {
        IterMat<MAXN, MAXN, matMin> itMin(0, i);
        IterMat<MAXN, MAXN, matMax> itMax(0, i);
         
        GetMinMaxFromSequence(mat[i], n, k, itMin, itMax);
    }
}
 
inline static void SetMinMaxDiff(MinMaxDiff& diffMinMax, const short diff)
{
    if (diff < diffMinMax.Diff)
    {
        diffMinMax.Diff = diff;
        diffMinMax.Count = 1;
    }
    else if (diff == diffMinMax.Diff)
    {
        ++diffMinMax.Count;
    }
}
 
static void GetMinMaxMinDiffForSequence(const short seqMin[], const short seqMax[], const int n, const int k, MinMaxDiff& diffMinMax)
{
    deque<Entry> deqMin;
    deque<Entry> deqMax;
 
    for (int i=0; i<k; ++i)
    {
        PopBackElements<EntryValuesGreater>(deqMin, seqMin[i]);
        deqMin.push_back(Entry(seqMin[i], i));
         
        PopBackElements<EntryValuesLess>(deqMax, seqMax[i]);
        deqMax.push_back(Entry(seqMax[i], i));
    }
 
    SetMinMaxDiff(diffMinMax, deqMax.front().Value - deqMin.front().Value);
     
    for (int i=k; i<n; ++i)
    {
        PopBackElements<EntryValuesGreater>(deqMin, seqMin[i]);
        deqMin.push_back(Entry(seqMin[i], i));
         
        if (deqMin.front().Position <= i-k)
        {
            deqMin.pop_front();
        }
         
        PopBackElements<EntryValuesLess>(deqMax, seqMax[i]);
        deqMax.push_back(Entry(seqMax[i], i));
         
        if (deqMax.front().Position <= i-k)
        {
            deqMax.pop_front();
        }
         
        SetMinMaxDiff(diffMinMax, deqMax.front().Value - deqMin.front().Value);
    }
}
 
static void GetMinMaxMinDiff(const int m, const int n, const int k, MinMaxDiff& diffMinMax)
{
    for (int i=0; i<m; ++i)
    {
        GetMinMaxMinDiffForSequence(matMin[i], matMax[i], n, k, diffMinMax);
    }
}
 
template<int M, int N>
static void PrintMatrix(const short (&mat)[N][M], int m, int n)
{
    ostream_iterator<short> itOut(cout, " ");
    for (int i=0; i<m; ++i)
    {
        copy(mat[i], mat[i] + n, itOut);
        cout << endl;
    }
    cout << endl;
}
 
template<int M, int N>
static void ClearMatrix(short (&mat)[N][M], int m, int n)
{
    for (int i=0; i<m; ++i)
    {
        memset(mat, 0, n*sizeof(short));
    }
}
 
int main()
{
    int m, n, p;
    int DX, DY;
    fstream fin("struti.in", fstream::in);
    fstream fout("struti.out", fstream::out);
     
    fin >> m >> n >> p;
    //cout << m << " " << n << " " << p << "\n";
     
    for (int i=0; i<m; ++i)
    {
        for (int j=0; j<n; ++j)
        {
            fin >> mat[i][j];
            //cout << mat[i][j] << " ";
        }
        //cout << "\n";
    }
     
    for (int i=0; i<p; ++i)
    {
        fin >> DX >> DY;
        //cout << DX << " " << DY << "\n";
         
        if (DX < DY)
        {
            swap(DX, DY);
        }
         
        MinMaxDiff diffMinMax;
         
        PopulateMinMaxArray(m, n, DX);
        GetMinMaxMinDiff(n - DX + 1, m, DY, diffMinMax);
         
        //PrintMatrix(matMin, n - DX + 1, m);
        //PrintMatrix(matMax, n - DX + 1, m);
         
        if (DX != DY)
        {
            //ClearMatrix(matMin, m, n);
            //ClearMatrix(matMax, m, n);
            PopulateMinMaxArray(m, n, DY);        
            GetMinMaxMinDiff(n - DY + 1, m, DX, diffMinMax);
             
            //PrintMatrix(matMin, n - DY + 1, m);
            //PrintMatrix(matMax, n - DY + 1, m);
        }
         
        //ClearMatrix(matMin, m, n);
        //ClearMatrix(matMax, m, n);
 
        //cout << "Here\n";
        fout << diffMinMax.Diff << " " << diffMinMax.Count << "\n";
    }
     
    return 0;
}