Cod sursa(job #923149)

Utilizator vendettaSalajan Razvan vendetta Data 23 martie 2013 12:30:13
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.15 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>

using namespace std;

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

#define nmax 302
#define Qmax 20005
#define ll long long

int n, m, mat[nmax][nmax], a[nmax][nmax];
typedef struct {
    int val, x, y;
}Valori;
typedef struct {
    int x1, y1, x2, y2, rez, poz;
}Query;

Query q[Qmax];
Valori v[nmax*nmax];

const int dx[] = {0, -1, 0, 1};
const int dy[] = {-1, 0, 1, 0};
int t[nmax*nmax], Rez[Qmax];

void citeste(){
    f >> n >> m;
    int k = 0;
    for(int i=1; i<=n; ++i){
        for(int j=1; j<=n; ++j){
            f >> a[i][j];
            v[++k].val = a[i][j]; v[k].x = i; v[k].y = j;
            mat[i][j] = k;
        }
    }

    for(int i=1; i<=m; ++i){
        f >> q[i].x1 >> q[i].y1 >> q[i].x2 >> q[i].y2;
        q[i].poz = i;
    }
}

struct cmpVal{
    bool operator() (Valori A, Valori B){
        return (A.val > B.val);
    }
};

struct cmpQ{
    bool operator() (Query A, Query B){
        return (A.rez > B.rez);
    }
};

bool check(int x, int y){
    if (x > 0 && y > 0 && x <= n && y <= n) return 1;
    return 0;
}

inline int afla(int x){
    int x2 = x;
    for(; t[x]!=0; x=t[x]);
    while(x2 != x){
        int aux = t[x2];
        t[x2] = x;
        x2 = aux;
    }
    return x;
}

void uneste(int x, int y){
    if (x & 1 ) t[x] = y;
    else
    t[y] = x;
}

void baga(int X, int Val){
    int i = v[X].x; int j = v[X].y;
    int X2 = mat[ i ][ j ];
    for(int k=0; k<4; ++k){
        int newI = i + dx[k];
        int newJ = j + dy[k];
        if ( check( newI, newJ ) && a[newI][newJ] >= Val ){// insemana ca pot uni X cu vecincul curent
            int radX = afla(X2); int radVc = afla( mat[newI][newJ] );
            if (radX != radVc) uneste(radX, radVc);
        }
    }
}

void rezolva(){
    // ideea ar fi asa : formez bit cu bit rezultatul pentru fiecare query; am nevoie de cel mai amre cost => vin cu biti descrescator
    //acum sunt la bitul K si vreau sa il pun la fiecare query : smecheria e urmatoarea eu sortez descrescator query-urile fata de
    // solutiile pe care le are pana acum; si tot descrescator valorile din matrice; acum am un bit K fixat pe care vreau sa il pun
    // la fiecare query si sunt la query-ul i; eu stiu ca query[i].rez >= query[i+1].rez => orice valoarea pe care o bag la query-ul
    // i va fi bun si pt i+1; si cam pe obs asta se bazeaza toate solutia

    sort(v+1, v+n*n+1, cmpVal());// sortez descrescator valorile din matrice
    //for(int i=1; i<=n*n; ++i) cout << v[i].val << " "; cout << "\n";

    int lim = 0; for(; (1<<lim) <= v[1].val; ++lim);// acum 1<<lim > v[1].val => lim = lim - 1
    lim--;
    for(int k=lim; k>=0; --k){
    //for(int k=lim; k>=2; --k){
        for(int i=1; i<=n*n; ++i) t[i] = 0;// pt multimi disjuncte

        sort(q+1, q+m+1, cmpQ());
        int j=1;
        for(int i=1; i<=m; ++i){
            int newRez = q[i].rez + (1<<k);// incerc sa bag bitul k la rezultatul pentru query-ul i
            // acum bag toate valorile din matrice ce sunt >= cu newRez pt ca alea sunt bune
            //cout << i << " : ";
            for(; j<=n*n && v[j].val >= newRez; ++j){
                baga(j, newRez);// acum incerc sa unesc pe j cu ceva vecini
            }
            //cout << j << "\n";
            // acum vad daca pot baga la query-ul curent bitul k;
            int radA = afla( mat[ q[i].x1 ][ q[i].y1 ] );
            int radB = afla( mat[ q[i].x2 ][ q[i].y2 ] );
            //cout << radA << " " << radB << " " << mat[ q[i].x1 ][q[i].y1] << " " << mat[ q[i].x2][ q[i].y2]<< "\n";
            if ( radA == radB) q[i].rez += (1<<k);// exista drum a. i. toate valorile sa fie >= cu q[i].rez+(1<<k) => cel mai mare
            // cost a. i. sa se respecte propr din enunt e q[i].rez + (1<<k);
        }
    }

    for(int i=1; i<=m; ++i) Rez[ q[i].poz ] = q[i].rez;
    for(int i=1; i<=m; ++i){
        g << Rez[i] << "\n";
        //cout << Rez[i] << "\n";
    }

}

int main(){
    citeste();
    rezolva();

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

    return 0;
}