Cod sursa(job #2015633)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 26 august 2017 20:53:39
Problema Struti Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.41 kb
#include <iostream>
#include <fstream>
#include <stack>
#include <vector>
#include <deque>

using namespace std;
const int inf = 3e4 + 5;
const int NMax = 1e3 + 5;

class parser { // pentru parsare
    using integer = short;
    static const int strMax = 6*NMax*NMax + 50;

    ifstream in;
    char str[strMax],*p;

    public:
    parser(const string& s) {
        in.open(s);
        in.get(str,strMax,1);
        p = str;
    }

    parser& operator>> (integer& nr) {
        while ( !( ('0' <= *p && *p <= '9') || *p == '\0') ) {
            ++p;
        }

        int temp = 0;
        while ('0' <= *p && *p <= '9') {
            temp = temp * 10 + *p++ - '0';
        }
        nr = temp;

        return *this;
    }
    void close() {
        in.close();
    }
};
parser pin("struti.in");
ofstream out("struti.out");

#define ll long long
#define ull unsigned long long
#define pb push_back
using zint = short;

zint N,M,P;
zint a[NMax][NMax],rmn[NMax][NMax],rmx[NMax][NMax];
pair<zint,zint> dmn[NMax],dmx[NMax];
const pair<zint,zint> def = pair<zint,zint>(1,0);
// a[i][j] - altitudinea din zona (i,j);
// rmn[i][j] = min( a[i][j-dy+1], a[i][j-dy+2], ..., a[i][j] );
// rmx[i][j] = max( a[i][j-dy+1], a[i][j-dy+2], ..., a[i][j] );
// unde dx,dy depind de query;
// dmn - deque implementat manual pentru determinarea minimului pe o secventa de lungime dx/dy;
// dmx - deque implementat manual pentru determinarea maximului pe o secventa de lungime dx/dy;
// def - valoare pentru a reseta un deque;
// deque[0].first = pozitia pe care se afla primul element al deque-ului, cel din "fata";
// deque[0].second = pozitia pe care se afla ultimul element al deque-ului, cel din "spate";
// else:
// pair.first = indexul liniei/coloanei de pe care s-a obtinut valoarea pair.second;

void solve(zint,zint,zint&,int&);
void insertMax(pair<zint,zint>*,zint,zint,zint);
void insertMin(pair<zint,zint>*,zint,zint,zint);

int main() {
    pin>>N>>M>>P;
    for (zint i=1;i <= N;++i) {
        for (zint j=1;j <= M;++j) {
            pin>>a[i][j];
        }
    }

    while (P--) {
        zint dx,dy,min1,min2;
        int nrMin1,nrMin2;
        pin>>dx>>dy;

        solve(dx,dy,min1,nrMin1);
        if (dx != dy) {
            solve(dy,dx,min2,nrMin2);

            if (min1 == min2) {
                nrMin1 += nrMin2;
            }
            else if (min1 > min2) {
                min1 = min2;
                nrMin1 = nrMin2;
            }
        }

        out<<min1<<' '<<nrMin1<<'\n';
    }

    pin.close();out.close();
    return 0;
}

// gaseste minimul unei diferente de altitudine dintr-un
// dreptunghi de dimensiune (dx,dy), cat si numarul acestor dreptunghiuri
// si le pune in mn,nrMin;
void solve(zint dx,zint dy,zint& mn,int& nrMin) {
    for (zint i=1;i <= N;++i) {
        dmn[0] = dmx[0] = def;

        for (zint j=1;j <= M;++j) {
            insertMin(dmn,j,a[i][j],dy);
            insertMax(dmx,j,a[i][j],dy);

            rmn[i][j] = dmn[ dmn[0].first ].second;
            rmx[i][j] = dmx[ dmx[0].first ].second;
        }
    }

    mn = inf, nrMin = 0;
    for (zint j=dy;j <= M;++j) {
        dmn[0] = dmx[0] = def;

        for (zint i=1;i <= N;++i) {
            insertMin(dmn,i,rmn[i][j],dx);
            insertMax(dmx,i,rmx[i][j],dx);

            if (i >= dx) {
                zint val = dmx[ dmx[0].first ].second - dmn[ dmn[0].first ].second;

                if (mn > val) {
                    mn = val;
                    nrMin = 1;
                }
                else if (mn == val) {
                    ++nrMin;
                }
            }
        }
    }
}

// adauga o valoare intr-un deque menit sa tina maximul pe o secventa;
void insertMax(pair<zint,zint> *d,zint idx,zint val,zint len) {
    while (d[0].first <= d[0].second && d[ d[0].second ].second <= val) {
        --d[0].second;
    }
    d[ ++d[0].second ] = pair<zint,zint>(idx,val);

    if (d[ d[0].first ].first == idx - len) {
        ++d[0].first;
    }
}

// adauga o valoare intr-un deque menit sa tina minimul pe o secventa;
void insertMin(pair<zint,zint> *d,zint idx,zint val,zint len) {
    while (d[0].first <= d[0].second && d[ d[0].second ].second >= val) {
        --d[0].second;
    }
    d[ ++d[0].second ] = pair<zint,zint>(idx,val);

    if (d[ d[0].first ].first == idx - len) {
        ++d[0].first;
    }
}