Cod sursa(job #774842)

Utilizator vendettaSalajan Razvan vendetta Data 6 august 2012 15:50:55
Problema Struti Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.83 kb
#include <iostream>
#include <fstream>
#include <deque>

using namespace std;

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

#define nmax 1003
#define inf (1<<30)
#define Cifmax 5000000

int m, n, P, a[nmax][nmax], Min[nmax][nmax], Max[nmax][nmax];
int dq_min[nmax], dq_max[nmax];
int rez, cate;
char S[Cifmax];
int poz;

void citeste_buf(int &nr){

    nr = 0;

    for(; S[poz]<'0' || S[poz]>'9'; poz++);

    for(; S[poz]>='0' && S[poz]<='9'; poz++){
        nr = nr * 10 + (S[poz] - '0');
    }

}

void citeste(){

	f >> m >> n >> P;//
	f.get();
	f.getline(S, Cifmax, EOF);//iau tot fisierul
	for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++){
            citeste_buf(a[i][j]);
        }
	}
	/*
	for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++) f >> a[i][j];
	}
    */
}

void deck_pe_coloana(int i, int j, int &St, int &Dr, int X, int cod){

    if (cod == -1){//pt minim
        while(St<=Dr && a[i][j] < a[ dq_min[Dr] ][j]) --Dr;
        dq_min[++Dr] = i;

        //while(St<=Dr && dq_min[St] + X-1 < i) ++St;
        if (dq_min[St] + X-1 < i) ++St;

        Min[i][j] = a[ dq_min[St] ][j];

    }else if (cod == 1){//pt max
        while(St<=Dr && a[i][j] > a[ dq_max[Dr] ][j]) --Dr;
        dq_max[++Dr] = i;

        //while(St<=Dr && dq_max[St]+X-1 < i) ++St;
        if (dq_max[St]+X-1 < i) ++St;
        Max[i][j] = a[ dq_max[St] ][j];
    }

}

void deck_pe_linie(int i, int j, int &St, int &Dr, int X, int cod){

    if (cod == -1){//pt minim
        while(St <= Dr && Min[i][j] < Min[i][ dq_min[Dr] ]) --Dr;
        dq_min[++Dr] = j;

        //while(St<=Dr && dq_min[St] + X-1 < j) ++St;

        if (dq_min[St] + X-1 < j) ++St;

    }else if(cod == 1){
        while(St <= Dr && Max[i][j] > Max[i][ dq_max[Dr] ]) --Dr;
        dq_max[++Dr] = j;

        //while(St <= Dr && dq_max[St]+X-1 < j) ++St;
        if (dq_max[St]+X-1 < j) ++St;

    }

}

void afla(int X, int Y){

    //X = x e paralel cu axa Oy;
    // Y paralel cu axa Ox

    //aflu pentru fiecare secventa de X elemente din fiecare coloana Minimul, respectiv Maximul
    //m = nr de linii; si n = nr de coloane
    for(int j=1; j<=n; j++){
        int St_min = 1;
        int Dr_min = 0;
        int St_max = 1;
        int Dr_max = 0;
        for(int i=1; i<=m; i++){
            //minimul
            deck_pe_coloana(i, j, St_min, Dr_min, X, -1);

            //maximul
            deck_pe_coloana(i, j, St_max, Dr_max, X, 1);
        }
    }

    //acum aflu pentru fiecare linie (pe care se termin un drepunghi) adica de la X in jos; si pentru fiecare secventa de Y elemente de pe fiecare linie
    //aflue Min rescpectiv Max

    for(int i=X; i<=m; i++){
        int St_min = 1; int Dr_min = 0;
        int St_max = 1; int Dr_max = 0;
        for(int j=1; j<=n; j++){
            //minimul
            deck_pe_linie(i, j, St_min, Dr_min, Y, -1);

            //maximul
            deck_pe_linie(i, j, St_max, Dr_max, Y, 1);

            if (j >= Y){
                int x = Min[i][ dq_min[St_min] ];
                int y = Max[i][ dq_max[St_max] ];
                if( y - x < rez){
                    rez = y-x;
                    cate = 1;
                }else if (y - x == rez){
                    ++cate;
                }
            }
        }
    }

}

void rezolva(){

    //citesc P perechi de dimensiuni de dreptunghiuri; trebuie sa caut un dreptunghi care are diferenta intre Max si Min cat mai mica

    for(int i=1; i<=P; i++){
        int X, Y;
        citeste_buf(X);
        citeste_buf(Y);
        rez = inf;
        cate = 0;
        afla(X,Y);

        if (X != Y)afla(Y,X);
        g << rez << " " << cate << "\n";
    }

}

int main(){

    citeste();
    rezolva();

    f.close();
    g.close();

    return 0;

}