Cod sursa(job #1653352)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 15 martie 2016 21:43:26
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.57 kb
#include <fstream>
#include <algorithm>

using namespace std;

const int MAX_N = 300;
const int MAX_Q = 20000;
const int MAX_KEY = 1000000;
const int NUM_DIR = 4;
const int DIR[NUM_DIR][2] = { {-1, 0}, {0, 1}, {1, 0}, {0, -1} };

int A[MAX_N * MAX_N + 1];
int Ind[MAX_N * MAX_N + 1];

int Parent[MAX_N * MAX_N];
int Size[MAX_N * MAX_N];

pair <int, int> T[MAX_Q];
int QInd[MAX_Q];
int Ans[MAX_Q];

inline
int GetFather(int u) {
    if (u == Parent[u]) {
        return u;
    }
    return Parent[u] = GetFather(Parent[u]);
}

inline
void UnionSet(int u, int v) {
    u = GetFather(u);
    v = GetFather(v);

    if (u != v) {
        if (Size[u] < Size[v]) {
            swap(u, v);
        }
        Parent[v] = u;
        Size[u] += Size[v];
    }
}

int main() {
    ifstream fin("matrice2.in");
    ofstream fout("matrice2.out");
    fin.tie(0);
    ios_base::sync_with_stdio(false);

    int N, Q; fin >> N >> Q;

    for (int i = 0; i < N * N; ++ i) {
        fin >> A[i];
        Ind[i] = i;
    }
    A[N * N] = -1;
    Ind[N * N] = N * N;

    sort(Ind, Ind + N * N, [] (const int &X, const int &Y) {
        return A[X] > A[Y];
    });

    for (int i = 0; i < Q; ++ i) {
        for (int j = 0; j <= 1; ++ j) {
            int X, Y; fin >> X >> Y;
            T[i].first = (X - 1) * N + Y - 1;
            swap(T[i].first, T[i].second);
        }
        Ans[i] = 0; QInd[i] = i;
    }
    fin.close();

    for (int step = 1 << 19; step; step >>= 1) {
        sort(QInd, QInd + Q, [] (const int &A, const int &B) {
            return Ans[A] > Ans[B];
        });

        for (int i = 0; i < N * N; ++ i) {
            Parent[i] = i;
            Size[i] = 1;
        }

        int ptr = 0;
        for (int i = 0; i < Q; ++ i) {
            int nextStep = Ans[QInd[i]] | step;

            while (A[Ind[ptr]] >= nextStep) {
                int X = Ind[ptr] / N;
                int Y = Ind[ptr] - X * N;
                for (int j = 0; j < NUM_DIR; ++ j) {
                    int x = X + DIR[j][0];
                    int y = Y + DIR[j][1];

                    if (x >= 0 && y >= 0 && x < N && y < N && A[x * N + y] >= nextStep) {
                        UnionSet(Ind[ptr], x * N + y);
                    }
                }
                ++ ptr;
            }
            Ans[QInd[i]] |= step & -(GetFather(T[QInd[i]].first) == GetFather(T[QInd[i]].second));
        }
    }

    for (int i = 0; i < Q; ++ i) {
        fout << Ans[i] << '\n';
    }
    fin.close();
    fout.close();

    return 0;
}