Cod sursa(job #1825519)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 9 decembrie 2016 12:16:44
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.33 kb
#include <fstream>
#include <algorithm>

using namespace std;

const int NMAX = 300 + 5;

int father[2 * NMAX * NMAX];
int h[2 * NMAX * NMAX];
int cost[2 * NMAX * NMAX];
int ancestor[2 * NMAX * NMAX];

void init(int lim) {
    for (int i = 1; i <= lim; ++ i)
        father[i] = i, ancestor[i] = i, h[i] = 0;
}

int find(int node) {
    if (father[node] != father[father[node]])
        father[node] = find(father[node]);
    return father[node];
}

vector <int> tree[2 * NMAX * NMAX];

int nodes;
void unite1(int a, int b, int val) {
    a = find(a), b = find(b);
    if (a == b)
        return ;

    ++ nodes;
    tree[nodes].push_back(ancestor[a]);
    tree[nodes].push_back(ancestor[b]);
    cost[nodes] = val;

    if (h[a] < h[b]) {
        father[a] = b;
        ancestor[b] = nodes;
    }
    else {
        if (h[a] == h[b])
            ++ h[a];
        father[b] = a;
        ancestor[a] = nodes;
    }
    return ;
}

void unite2(int a, int b) {
    a = find(a), b = find(b);
    if (a == b)
        return ;

    if (h[a] < h[b])
        father[a] = b;
    else {
        if (h[a] == h[b])
            ++ h[a];
        father[b] = a;
    }
    return ;
}

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

int encode(int lin, int col) {
    return (lin - 1) * n + col;
}

void addCell(int lin, int col, int val) {
    static const int dLin[] = {0, 0, 1, -1};
    static const int dCol[] = {1, -1, 0, 0};

    for (int k = 0; k < 4; ++ k) {
        int nLin = lin + dLin[k];
        int nCol = col + dCol[k];

        if (nLin >= 1 && nCol >= 1 && nLin <= n && nCol <= n && mat[nLin][nCol] >= mat[lin][col])
            unite1(encode(nLin, nCol), encode(lin, col), val);
    }
}

vector <pair <int, pair <int, int > > > cells;

int first[2 * NMAX * NMAX];
int firstSz;

void dfs(int node) {
    first[node] = ++ firstSz;
    for (auto it: tree[node]) {
        //father[it] = node;
        //h[it] = 1 + h[node];
        dfs(it);
    }
}

int bruteLca(int a, int b) {
    while (a != b) {
        if (h[a] > h[b])
            a = father[a];
        else
            b = father[b];
    }

    return a;
}

vector <pair <int, int> > queries[NMAX * NMAX];

const int QMAX = 20000 + 5;
int ans[QMAX];

void TarjanLca(int node) {
    for (auto it: tree[node]) {
        TarjanLca(it);
        unite2(node, it);
        ancestor[find(node)] = node;
    }

    if (node <= n * n)
        for (auto it: queries[node])
            ans[it.second] = cost[ancestor[find(it.first)]];
}

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

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

    for (int i = 1; i <= n; ++ i)
        for (int j = 1; j <= n; ++ j)
            cells.push_back({-mat[i][j], {i, j}});
    sort(cells.begin(), cells.end());

    nodes = n * n;
    init(2 * nodes);

    for (auto it: cells)
        addCell(it.second.first, it.second.second, -it.first);

    dfs(nodes);

    for (int i = 1; i <= q; ++ i) {
        int l1, c1, l2, c2;
        cin >> l1 >> c1;
        cin >> l2 >> c2;

        int a = encode(l1, c1);
        int b = encode(l2, c2);

        if (first[a] > first[b])
            swap(a, b);

        queries[b].push_back(make_pair(a, i));
    }

    init(nodes);
    TarjanLca(nodes);

    for (int i = 1; i <= q; ++ i)
        cout << ans[i] << '\n';
    return 0;
}