Pagini recente » Cod sursa (job #2520449) | Cod sursa (job #820561) | Cod sursa (job #547314) | Cod sursa (job #203459) | Cod sursa (job #923149)
Cod sursa(job #923149)
#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;
}