Cod sursa(job #790589)

Utilizator vendettaSalajan Razvan vendetta Data 21 septembrie 2012 20:34:01
Problema Plantatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.79 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>

using namespace std;

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

#define nmax 505
#define LogMax 10
#define ll long long

int n, m, a[nmax][nmax];
int Max[LogMax][nmax][nmax], Log[nmax];

void citeste(){

    f >> n >> m;//dimensiunea matricei; numarul de query-uri
    for(int i=1; i<=n; ++i){
        for(int j=1; j<=n; ++j) f >> a[i][j];
    }

}

void preprocesare(){

    //initializez matricea;
    for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) Max[0][i][j] = a[i][j];

    for(int k=1; k<LogMax; ++k){
        for(int i=1; i+(1<<k)-1<=n; ++i){
            for(int j=1; j+(1<<k)-1<=n; ++j){
                //acum am patru cazuri : defapt e asa ai un patrat mare pe care il poti imparti in patru patrate mai mici =>
                //odata pot ramane la patratul i,j,k-1 al II-lea : i+(2^(k-1)),j,k-1
                //al 3 lea : i, j+(2^(k-1)),k-1;
                //al 4 lea : i+( 2^(k-1), j+( 2^(k-1) ), k-1;
                Max[k][i][j] = Max[k-1][i][j];//pe primul patrat;

                int new_i = i+( 1<<(k-1) );
                Max[k][i][j] = max(Max[k][i][j], Max[k-1][new_i][j]);

                int new_j = j+( 1<<(k-1) );
                Max[k][i][j] = max(Max[k][i][j], Max[k-1][i][new_j]);

                Max[k][i][j] = max(Max[k][i][j], Max[k-1][new_i][new_j]);
            }
        }
    }

}

void rezolva(){

    //pentru fiecare query de forma x, y, k trebuie sa precizes valoarea maxima din dreptunghiul cu coltul stanga sus in x,y de latura k
    //asa ca fac un rmq in 2D;// mai exact imi preprocesez Max[k][i][j] = valoarea maxima din drepuntghiul cu coltul stanga sus in i, j, si
    //coltul dreapta jos in [i+2^k-1, j+2^k-1]

    preprocesare();

    //imi fac Log[i] = pozitia celui mai semnificativ bit de 1 din reprez binara a lui i

    for(int i=2; i<=n; ++i) Log[i] = Log[i/2] + 1;

    for(int i=1; i<=m; ++i){
        int x, y, latura;
        f >> x >> y >> latura;
        int x2 = x + latura-1;
        int y2 = y + latura-1;//coltul dreapta jos al dreaptunghiul
        //cout << x << " " << y << "\n";
        //fac la fel ca si rmq 1D;
        //latura defepat e lungimea intervalului
        //caut cel mai mare k a. i. 2^k <= latura-1
        int k = Log[latura];
        //cout << k << "\n";
        int rez = Max[k][x][y];

        //aflu celelalte 3 intervale
        int newX = x2 - (1<<k) + 1;
        int newY = y2 - (1<<k) + 1;
        rez = max(rez, Max[k][newX][y]);
        rez = max(rez, Max[k][x][newY]);
        rez = max(rez, Max[k][newX][newY]);
        g << rez << "\n";
    }

}

int main(){

    citeste();
    rezolva();

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

    return 0;

}