Cod sursa(job #898142)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 28 februarie 2013 06:40:51
Problema Struti Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 7.67 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 <typename T>
class deque
{
public:
    deque() :
        startIndex(0),
        endIndex(0)
    {}
    
    const T& back() const
    {
        return container[endIndex-1];
    }
    
    const T& front() const
    {
        return container[startIndex];
    }
    
    void push_back(T element)
    {
        container[endIndex] = element;
        ++endIndex;
    }
    
    void pop_back()
    {
        --endIndex;
    }
    
    void pop_front()
    {
        ++startIndex;
    }
    
    bool empty() const
    {
        return (startIndex == endIndex);
    }
    
    void clear()
    {
        startIndex = 0;
        endIndex = 0;
    }

private:
    short startIndex;
    short endIndex;
    
    T container[MAXN];
};

deque<Entry> deqMin;
deque<Entry> deqMax;

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;
    }
    
    deqMin.clear();
    deqMax.clear();
}

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;
    }

    
    //diffMinMax.Count = diffMinMax.Count * (diff == diffMinMax.Diff) + (diff <= diffMinMax.Diff);
    //diffMinMax.Diff = diff ^ ((diffMinMax.Diff ^ diff) & -(diffMinMax.Diff < diff));
}

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);
    }
    
    deqMin.clear();
    deqMax.clear();
}

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;
}