Cod sursa(job #2804836)

Utilizator Theodor17Pirnog Theodor Ioan Theodor17 Data 21 noiembrie 2021 12:35:03
Problema Struti Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.2 kb
/*

Pirnog Theodor Ioan
Colegiul National "B. P. Hasdeu"

*/

#include <fstream>
#include <deque>

using namespace std;

ifstream cin("struti.in");
ofstream cout("struti.out");

const int NMAX = 1e3;
int minim_linie[NMAX + 1][NMAX + 1], maxim_linie[NMAX + 1][NMAX + 1], minim_submat[NMAX + 1][NMAX + 1], maxim_submat[NMAX + 1][NMAX + 1];
int n, m, p, dx, dy, a[NMAX + 1][NMAX + 1];

void read(){

    cin >> n >> m >> p;

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            cin >> a[i][j];

}

void clear(){

    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){

            minim_linie[i][j] = maxim_linie[i][j] = 0;
            minim_submat[i][j] = maxim_submat[i][j] = 0;

        }
    }

}

void build_min_lin(){

    // construiesc minimele pe fiecare linie, avand grija la faptul ca imi este impusa o anumita lungime pentru secventa

    for(int i = 1; i <= n; i++){

        deque <int> dq;

        for(int j = 1; j <= m; j++){

            while(!dq.empty() && a[i][j] <= a[i][dq.back()])
                dq.pop_back();

            dq.push_back(j);

            while(!dq.empty() && dq.front() <= j - dy)
                dq.pop_front();
            
            if(dq.back() >= dy)
                minim_linie[i][j] = a[i][dq.front()];

        }

    }

}

void build_max_lin(){

    // construiesc maximele pe linie, avand grija la faptul ca imi este impusa o anumita lungime pentru secventa

    for(int i = 1; i <= n; i++){

        deque <int> dq;

        for(int j = 1; j <= m; j++){

            while(!dq.empty() && a[i][j] >= a[i][dq.back()])
                dq.pop_back();

            dq.push_back(j);

            while(!dq.empty() && dq.front() <= j - dy)
                dq.pop_front();
            
            if(dq.back() >= dy)
                maxim_linie[i][j] = a[i][dq.front()];

        }

    }

}

void build_min(){

    // parcurgerea se va face acum pe coloane, intrucat trebuie sa am o legatura intre minimele si maximele pe linii
    // minim_submat[i][j] va fi valoarea minima din matricea de colt dreapta jos (i, j) si cu laturile dx (sau dy)

    for(int j = 1; j <= m; j++){

        deque <int> dq;

        for(int i = 1; i <= n; i++){

            while(!dq.empty() && minim_linie[i][j] <= minim_linie[dq.back()][j])
                dq.pop_back();
            
            dq.push_back(i);

            while(!dq.empty() && dq.front() <= i - dx)
                dq.pop_front();
            
            if(i >= dx)
                minim_submat[i][j] = minim_linie[dq.front()][j];

        }

    }

}

void build_max(){

    // parcurgerea se va face acum pe coloane, intrucat trebuie sa am o legatura intre minimele si maximele pe linii
    // minim_submat[i][j] va fi valoarea minima din matricea de colt dreapta jos (i, j) si cu laturile dx (sau dy)

    for(int j = 1; j <= m; j++){

        deque <int> dq;

        for(int i = 1; i <= n; i++){

            while(!dq.empty() && maxim_linie[i][j] >= maxim_linie[dq.back()][j])
                dq.pop_back();
            
            dq.push_back(i);

            while(!dq.empty() && dq.front() <= i - dx)
                dq.pop_front();
            
            if(i >= dx)
                maxim_submat[i][j] = maxim_linie[dq.front()][j];

        }

    }

}

void compare(int &dif_min, int &k){

    // caut oferta cea mai convenabila(de diferenta minima) si numarul de oferte existente cu aceasta diferenta

    int dif = 0;

    for(int i = dx; i <= n; i++){
        for(int j = dy; j <= m; j++){

            dif = maxim_submat[i][j] - minim_submat[i][j];

            if(dif < dif_min){

                dif_min = dif;
                k = 1;

            }else if(dif == dif_min)
                k++;


        }
    }

}

void build(int &dif_min, int &k){

    clear();
    build_min_lin();
    build_max_lin();
    build_min();
    build_max();
    compare(dif_min, k);

}

void solve(){

    int dif_min = 0, k = 0;

    for(int i = 1; i <= p; i++){

        dif_min = int(1e9);
        k = 0;
        
        cin >> dx >> dy;
        build(dif_min, k);

        if(dx != dy){

            swap(dx, dy);
            build(dif_min, k);

        }

        cout << dif_min << " " << k << "\n";
    
    }

}

int main(){

    read();
    solve();

}