Cod sursa(job #1044929)

Utilizator mathboyDragos-Alin Rotaru mathboy Data 30 noiembrie 2013 16:56:18
Problema Matrice 2 Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.81 kb
#include <cstdio>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <cstring>
#include <string>
#include <set>
#include <stack>
#define pb push_back

#define mp make_pair
#define f first
#define s second
#define ll long long

const int MAXN = 305;

using namespace std;

int marked[MAXN][MAXN];
int T[MAXN * MAXN];
class nodeMatrix {
    public:
    int val;
    int x, y;
    int id;
    nodeMatrix() {
        x = y = id = val = 0;
    }

    nodeMatrix(int _val, int _x, int _y, int _id) {
        val = _val;
        x = _x;
        y = _y;
        id = _id;
    }
    bool operator > (const nodeMatrix &next) const {
        return val > next.val;
    }
};
class nodeQuery {
    public:
    int x1, y1, x2, y2, id;
    int val;
    nodeQuery() {
        x1 = y1 = x2 = y2 = id = 0;
    }
    nodeQuery(int _x1, int _y1, int _x2, int _y2, int _id) {
        x1 = _x1; y1 = _y1; 
        x2 = _x2; y2 = _y2;
        id = _id;
    }
    bool operator > (const nodeQuery &next) const{
        return val > next.val;
    }
};


int find(int id1) {
    if(id1 == -1) {
        return -1;
    }
    int x = id1;
    while(T[x] != x) {
        x = T[x];
    }
    while(T[id1] != id1) {
        int aux = T[id1];
        T[id1] = x;
        id1 = aux;
    }
    return x;
}
void unite(int id1, int id2) {
    int r = rand() % 2;
    if(r & 1) {
        T[find(id1)] = find(id2);
    } else {
        T[find(id2)] = find(id1);
    }
}
void insert(nodeMatrix v, int N) {
    marked[v.x][v.y] = find(v.id);
    int dx[4] = {0, 0, -1, 1};
    int dy[4] = {1, -1, 0, 0};
    
    for (int i = 0; i < 4; ++i) {
        if (v.x + dx[i] < N && v.x + dx[i] >= 0) {
            if (v.y + dy[i] < N && v.y + dy[i] >= 0) {
                if (marked[v.x + dx[i]][v.y + dy[i]] != -1) {
                    unite(marked[v.x][v.y], marked[v.x + dx[i]][v.y + dy[i]]);
                }
            }
        }
    }
}
inline bool same(int p1, int p2) {
    if(p1 == -1 || p2 == -1) {
        return 0;
    }
    return find(p1) == find(p2);
}
int main() {
    ifstream cin("matrice2.in");
    ofstream cout("matrice2.out");
    
    int N, Q; cin >> N >> Q;
    vector <nodeMatrix> values(N * N);
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            int a; cin >> a;
            values[i * N + j] = nodeMatrix(a, i, j, i * N + j); 
        }
    }
    sort(values.begin(), values.end(), greater<nodeMatrix>()); 
    vector<nodeQuery> query(Q);
    
    for (int i = 0; i < Q; ++i) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a -= 1; b -= 1; 
        c -= 1; d -= 1;
        query[i] = nodeQuery(a, b, c, d, i);
    }
    
    for (int step = 20; step >= 0; --step) {
        
        memset(marked, -1, sizeof(marked));
        for (int i = 0; i < N * N; ++i) {
            T[i] = i;
        }
        int jump_value = (1 << step);
        int current = 0;
        
        for (int i = 0; i < N * N; ++i) {
            insert(values[i], N);
            if (i != N * N - 1) {
                if (values[i].val == values[i + 1].val) {
                    continue;
                }
            }
            while (query[current].val + jump_value >= values[i].val && current < Q) {
                int x1 = query[current].x1, x2 = query[current].x2;
                int y1 = query[current].y1, y2 = query[current].y2;
                 
                if (same(marked[x1][y1], marked[x2][y2])) {
                    query[current].val += jump_value;
                }
                current += 1;
            }
        }
        sort(query.begin(), query.end(), greater<nodeQuery>());
    }
    vector <int> answer(Q);

    for (int i = 0; i < Q; ++i) {
        answer[query[i].id] = query[i].val;
    }
    for (int i = 0; i < Q; ++i) {
        cout << answer[i] << "\n";
    }
    return 0;
}