Cod sursa(job #1533249)

Utilizator felixiPuscasu Felix felixi Data 22 noiembrie 2015 12:21:30
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.92 kb
#include <algorithm>
#include <fstream>
#include <cassert>
#include <vector>
using namespace std;

const int Nmax = 305, Mmax = 100005;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};

int A[Nmax][Nmax];

vector<int> G[Mmax];
int N;

pair<int, int> cells[Mmax];
int Father[Mmax], DSU[Mmax], Lvl[Mmax], Pos[Mmax];
int Asc[17][Mmax];

inline int getKey(int x, int y) {
    return (x - 1) * N + y;
}

inline pair<int, int> getCell(int x) {
    return make_pair((x - 1) / N + 1, (x - 1) % N + 1);
}

int find(int x) {
    int y, p;
    for (y = x; DSU[y] != y; y = DSU[y]);
    for (; x != y; x = p) {
        p = DSU[x];
        DSU[x] = y;
    }
    return y;
}

int climb(int x, int nr) {
    for (int k = 16; k >= 0; --k) {
        if ((1 << k) <= nr) {
            x = Asc[k][x];
            nr -= 1 << k;
        }
    }
    return x;
}

int lca(int x, int y) {
    if (Lvl[x] < Lvl[y]) swap(x, y);
    if (Lvl[x] > Lvl[y]) x = climb(x, Lvl[x] - Lvl[y]);
    if (x == y) return x;
    for (int k = 16; k >= 0; --k) {
        if (Asc[k][x] != Asc[k][y]) {
            x = Asc[k][x];
            y = Asc[k][y];
        }
    }
    return Asc[0][x];
}

int main() {
    ifstream fin("matrice2.in");
    ofstream fout("matrice2.out");

    int Q;
    fin >> N >> Q;

    for (int i = 1; i <= N; ++i) {
        for (int j = 1; j <= N; ++j) {
            fin >> A[i][j];
            cells[getKey(i, j)] = {A[i][j], getKey(i, j)};
        }
    }

    sort(cells + 1, cells + N * N + 1);
    for (int i = N * N; i > 0; --i) {
        DSU[i] = i;
        Father[i] = i;
        Pos[cells[i].second] = i;
    }

    for (int i = N * N; i > 0; --i) {
        pair<int, int> cell = getCell(cells[i].second);
        int x = cell.first, y = cell.second, val = cells[i].first;

        for (int k = 0; k < 4; ++k) {
            int nx = x + dx[k], ny = y + dy[k];
            if (nx < 1 || nx > N || ny < 1 || ny > N) continue;
            int key = getKey(nx, ny);
            if (Pos[key] > i) {
                Father[find(key)] = cells[i].second;
                DSU[find(key)] = cells[i].second;
            }
        }
    }
    int M = N * N;
    for (int i = 1; i <= M; ++i) Asc[0][i] = Father[i];
    for (int k = 1; k < 17; ++k) {
        for (int i = 1; i <= M; ++i) {
            Asc[k][i] = Asc[k - 1][Asc[k - 1][i]];
        }
    }

    for (int i = 1; i <= M; ++i) {
        pair<int, int> f = getCell(i), s = getCell(Father[i]);
        assert(A[f.first][f.second] >= A[s.first][s.second]);
        Lvl[cells[i].second] = Lvl[Father[cells[i].second]] + 1;
    }

    while (Q-- > 0) {
        int x1, y1, x2, y2;
        fin >> x1 >> y1 >> x2 >> y2;

        int x = getKey(x1, y1), y = getKey(x2, y2);
        pair<int, int> cell = getCell(lca(x, y));

        fout << A[cell.first][cell.second] << '\n';
    }

    fin.close();
    fout.close();
}