Cod sursa(job #2015330)

Utilizator MaligMamaliga cu smantana Malig Data 25 august 2017 19:13:44
Problema Struti Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.34 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 {
    using integer = short;
    static const int strMax = 6*NMax*NMax + 50;

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

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

    parser& operator>> (integer& nr) {
        bool neg = 0;
        while ( !( ('0' <= *p && *p <= '9') || *p == '\0') ) {
            if (*p == '-') {
                neg ^= 1;
            }
            ++p;
        }

        if (*p == '\0') {
            nr = 0;
            failed = true;
            return *this;
        }

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

        return *this;
    }

    bool fail() {
        return failed;
    }

    void print() {
        cout<<str<<'\n';
    }

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

struct elem {
    zint idx,val;
    elem (zint _idx = 0,zint _val = 0) {
        idx = _idx;
        val = _val;
    }
};

void solve(zint,zint,zint&,int&);

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);
        //cout<<min1<<' '<<nrMin1<<'\n';
        if (dx != dy) {
            solve(dy,dx,min2,nrMin2);
            //cout<<min2<<' '<<nrMin2<<'\n';

            if (min1 == min2) {
                nrMin1 += nrMin2;
            }
            else if (min1 > min2) {
                min1 = min2;
                nrMin1 = nrMin2;
            }
        }
        //cout<<'\n';

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

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

void solve(zint dx,zint dy,zint& mn,int& nrMin) {
    deque<elem> colMn[NMax],colMx[NMax];

    mn = inf, nrMin = 0;
    for (int i=1;i <= N;++i) {
        for (int j=1;j <= M;++j) {

            while (colMn[j].size() && colMn[j].back().val >= a[i][j]) {
                colMn[j].pop_back();
            }
            colMn[j].push_back(elem(i,a[i][j]));
            if (colMn[j].front().idx == i-dx) {
                colMn[j].pop_front();
            }

            while (colMx[j].size() && colMx[j].back().val <= a[i][j]) {
                colMx[j].pop_back();
            }
            colMx[j].push_back(elem(i,a[i][j]));
            if (colMx[j].front().idx == i-dx) {
                colMx[j].pop_front();
            }

            //cout<<i<<' '<<rowMn[i].front()<<' '<<colMx[i].front()<<'\n';
        }
        //cout<<'\n';

        if (i >= dx) {
            deque<elem> rowMn,rowMx;

            for (int j=1;j <= M;++j) {
                while (rowMn.size() && rowMn.back().val >= colMn[j].front().val) {
                    rowMn.pop_back();
                }
                rowMn.push_back(elem(j,colMn[j].front().val));
                if (rowMn.front().idx == j-dy) {
                    rowMn.pop_front();
                }

                while (rowMx.size() && rowMx.back().val <= colMx[j].front().val) {
                    rowMx.pop_back();
                }
                rowMx.push_back(elem(j,colMx[j].front().val));
                if (rowMx.front().idx == j-dy) {
                    rowMx.pop_front();
                }

                //cout<<i<<' '<<rowMn.front()<<' '<<rowMx.front()<<"\n\n\n";

                if (j >= dy) {
                    short val = rowMx.front().val - rowMn.front().val;
                    //cout<<val<<"\n\n\n";
                    if (mn > val) {
                        mn = val;
                        nrMin = 1;
                    }
                    else if (mn == val) {
                        ++nrMin;
                    }
                }
            }
        }
    }

}