Cod sursa(job #1424139)

Utilizator linia_intaiConstantinescu Iordache Ciobanu Noi cei din linia intai linia_intai Data 23 aprilie 2015 16:51:35
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.97 kb
#include <fstream>
#include <algorithm>
#include <utility>
#include <cstring>

#define NMAX 305
#define QMAX 20005
using namespace std;

int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};

int n;
int mat[NMAX][NMAX];

class disjoint_sets {
    pair <int, int> mat[NMAX][NMAX];
    int h[NMAX][NMAX];

    pair <int, int> find (const pair <int, int> &cell) {
        if (mat[cell.first][cell.second] != cell)
            mat[cell.first][cell.second] = find(mat[cell.first][cell.second]);
        return mat[cell.first][cell.second];
    }

    inline void unite (pair <int, int> cell1, pair <int, int> cell2) {
        cell1 = find(cell1);
        cell2 = find(cell2);

        if (cell1 == cell2)
            return ;

        if (h[cell1.first][cell1.second] < h[cell2.first][cell2.second])
            mat[cell1.first][cell1.second] = cell2;
        else {
            mat[cell2.first][cell2.second] = cell1;
            if (h[cell1.first][cell1.second] == h[cell2.first][cell2.second])
                h[cell1.first][cell1.second] ++;
        }
    }

public:
    inline void init () {
        memset(h, 0, sizeof(h));

        int j;
        for (int i = 1; i <= n; i++)
            for (j = 1; j <= n; j++)
                mat[i][j] = make_pair(i, j);
    }

    disjoint_sets () {
        init();
    }

    inline void insert (const pair <int, int> &cell) {
        h[cell.first][cell.second] = 1;

        pair <int, int> aux;
        for (int k = 0; k < 4; k++) {
            aux.first = cell.first + dx[k];
            aux.second = cell.second + dy[k];

            if (aux.first > 0 && aux.second > 0 && aux.first <= n && aux.second <= n && h[aux.first][aux.second])
                unite(cell, aux);
        }
    }

    inline bool united (pair <int, int> cell1, pair <int, int> cell2) {
        cell1 = find(cell1);
        cell2 = find(cell2);

        return (cell1 == cell2);
    }
} Sets;

pair <int, int> elements[NMAX * NMAX];

bool cmp (const pair <int, int> &cell1, const pair <int, int> &cell2) {
    return mat[cell1.first][cell1.second] > mat[cell2.first][cell2.second];
}

int q;
struct query {
    pair <int, int> cell1, cell2;
    int pos;
} queries[QMAX], aux1[QMAX], aux2[QMAX];

int answers[QMAX];

bool operator< (const query &a, const query &b) {
    return answers[a.pos] > answers[b.pos];
}

int main()
{
    ifstream cin("matrice2.in");
    ofstream cout("matrice2.out");

    cin >> n >> q;

    int j;
    for (int i = 1; i <= n; i++)
        for (j = 1; j <= n; j++)
            cin >> mat[i][j];

    for (int i = 1; i <= n; i++)
        for (j = 1; j <= n; j++)
            elements[(i - 1) * n + j] = make_pair(i, j);
    sort(elements + 1, elements + n * n + 1, cmp);

    for (int i = 1; i <= q; i++) {
        cin >> queries[i].cell1.first >> queries[i].cell1.second >> queries[i].cell2.first >> queries[i].cell2.second;
        queries[i].pos = i;
    }

    //Parallel binary search
    int k, aux1l, aux2l;
    for (int i = 20; i >= 0; i--) { //Incercam sa adaugam  (1 << i)
        Sets.init();

        for (j = 1; j <= q; j++)
            answers[queries[j].pos] += (1 << i);

        k = 0;
        aux1l = 0, aux2l = 0;
        for (j = 1; j <= q; j++) {
            while (k + 1 <= n * n && mat[elements[k + 1].first][elements[k + 1].second] >= answers[queries[j].pos]) {
                k ++;
                Sets.insert(elements[k]);
            }
            if (Sets.united(queries[j].cell1, queries[j].cell2))
                aux1[++ aux1l] = queries[j];
            else {
                aux2[++ aux2l] = queries[j];
                answers[queries[j].pos] -= (1 << i);
            }
        }

        //Resortam query-urile
        merge(aux1 + 1, aux1 + aux1l + 1, aux2 + 1, aux2 + aux2l + 1, queries + 1);
    }

    //

    for (int i = 1; i <= q; i++)
        cout << answers[i] << '\n';

    cin.close();
    cout.close();
    return 0;
}