Cod sursa(job #2807505)

Utilizator rapidu36Victor Manz rapidu36 Data 23 noiembrie 2021 21:09:23
Problema Struti Scor 80
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.52 kb
#include <fstream>
#include <deque>
#include <iomanip>

using namespace std;

const int N = 1000;
const int INF = 1e4;

int nl, nc, a[N][N], mini[N][N], maxi[N][N];

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

void coloana_mini(int c, int dy)
{
    deque <int> d;
    for (int i = 0; i < nl; i++)
    {
        if (!d.empty() && d.front() == i - dy)
        {
            d.pop_front();
        }
        while (!d.empty() && a[d.back()][c] >= a[i][c])
        {
            d.pop_back();
        }
        d.push_back(i);
        mini[i][c] = a[d.front()][c];
    }
}

void calcul_mini(int dy)
{
    for (int j = 0; j < nc; j++)
    {
        coloana_mini(j, dy);
    }
}

void coloana_maxi(int c, int dy)
{
    deque <int> d;
    for (int i = 0; i < nl; i++)
    {
        if (!d.empty() && d.front() == i - dy)
        {
            d.pop_front();
        }
        while (!d.empty() && a[d.back()][c] <= a[i][c])
        {
            d.pop_back();
        }
        d.push_back(i);
        maxi[i][c] = a[d.front()][c];
    }
}

void calcul_maxi(int dy)
{
    for (int j = 0; j < nc; j++)
    {
        coloana_maxi(j, dy);
    }
}

void afis(int l1, int c1, int l2, int c2)
{
    for (int i = l1; i <= l2; i++)
    {
        for (int j = c1; j <= c2; j++)
        {
            out << setw(5) << a[i][j];
        }
        out << "\n";
    }
    out << "\n";
}

void diferenta_min(int dx, int dy, int &dif_min, int &nr)
{
    //out << "\ncalcul pentru dx = " << dx << " si dy = " << dy << "\n";
    calcul_mini(dy);
    calcul_maxi(dy);
    deque <int> dmin, dmax;
    for (int i = dy - 1; i < nl; i++)
    {
        dmin.clear();
        dmax.clear();
        for (int j = 0; j < nc; j++)
        {
            ///actualizez in deque-ul de minime
            if (!dmin.empty() && dmin.front() == j - dx)
            {
                dmin.pop_front();
            }
            while (!dmin.empty() && mini[i][dmin.back()] >= mini[i][j])
            {
                dmin.pop_back();
            }
            dmin.push_back(j);
            ///actualizez in deque-ul de maxime
            if (!dmax.empty() && dmax.front() == j - dx)
            {
                dmax.pop_front();
            }
            while (!dmax.empty() && maxi[i][dmax.back()] <= maxi[i][j])
            {
                dmax.pop_back();
            }
            dmax.push_back(j);
            if (j < dx - 1) continue;
            int rez_actual = maxi[i][dmax.front()] - mini[i][dmin.front()];
            //out << "(" << i << "," << j << "):\t" << maxi[i][dmax.front()] << " - " << mini[i][dmin.front()];
            //out << " = " << rez_actual << "\n";
            if (rez_actual < dif_min)
            {
                dif_min = rez_actual;
                nr = 1;
            }
            else if (rez_actual == dif_min)
            {
                nr++;
            }
        }
    }
}

void calcul(int dx, int dy)
{
    int difmin = INF, nr;
    diferenta_min(dx, dy, difmin, nr);
    if (dx != dy)
    {
        diferenta_min(dy, dx, difmin, nr);
    }
    out << difmin << " " << nr << "\n";
}

int main()
{
    int p;
    in >> nl >> nc >> p;
    for (int i = 0; i < nl; i++)
    {
        for (int j = 0; j < nc; j++)
        {
            in >> a[i][j];
        }
    }
    for (int i = 0; i < p; i++)
    {
        int dx, dy;
        in >> dx >> dy;
        calcul(dx, dy);
    }
    in.close();
    out.close();
    return 0;
}