Cod sursa(job #2701625)

Utilizator PatrickCplusplusPatrick Kristian Ondreovici PatrickCplusplus Data 31 ianuarie 2021 20:25:22
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.77 kb
#include <bits/stdc++.h>

using namespace std;

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

const int nmax = 305, qmax = 20005;
int n, q, mat[nmax][nmax], L[qmax], R[qmax], maxim, r[nmax * nmax], t[nmax * nmax], A[qmax], B[qmax], C[qmax], D[qmax];
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int ans[qmax];
vector <int> Event[nmax * nmax];
vector <pair <int, int> > G[nmax * nmax];
unordered_map <int, int> mp, mpInv;
void normalize(){
    vector <int> v;
    for (int i = 1; i <= n; ++i){
        for (int j = 1; j <= n; ++j){
            v.push_back(mat[i][j]);
        }
    }
    sort(v.begin(), v.end());
    int z = 1;
    mp[v[0]] = z;
    mpInv[z] = v[0];
    for (int i = 1; i < v.size(); ++i){
        if (v[i] != v[i - 1]){
            ++z;
        }
        mp[v[i]] = z;
        mpInv[z] = v[i];
    }
    for (int i = 1; i <= n; ++i){
        for (int j = 1; j <= n; ++j){
            mat[i][j] = mp[mat[i][j]];
        }
    }
}

bool Valid(int i, int j){
    return i >= 1 && j >= 1 && i <= n && j <= n;
}

int GetParent(int nod)
{
    int radacina = nod, copie_nod = nod;
    while (t[nod] != nod)
    {
        radacina = t[nod];
        nod = radacina;
    }
    while (t[copie_nod] != copie_nod)
    {
        int aux = t[copie_nod];
        t[copie_nod] = radacina;
        copie_nod = aux;
    }
    return radacina;
}

void Unite(int nod1, int nod2)
{
    int parent1 = GetParent(nod1);
    int parent2 = GetParent(nod2);
    if (parent1 == parent2)
    {
        return;
    }
    if (r[parent1] > r[parent2])
    {
        t[parent2] = parent1;
    }
    else if (r[parent1] < r[parent2])
    {
        t[parent1] = parent2;
    }
    else
    {
        t[parent1] = parent2;
        r[parent1]++;
    }
}

void Clear(){
    for (int i = 1; i <= maxim; ++i){
        Event[i].clear();
    }
    for (int i = 1; i <= n; ++i){
        for (int j = 1; j <= n; ++j){
            t[(i - 1) * n + j] = (i - 1) * n + j;
            r[(i - 1) * n + j] = 0;
        }
    }
}

void Apply(int i){
    for (auto it : G[i]){
        int x = it.first;
        int y = it.second;
        for (int k = 0; k < 4; ++k){
            int xx = x + dx[k];
            int yy = y + dy[k];
            if (Valid(xx, yy) && mat[xx][yy] >= i){
                Unite((x - 1) * n + y, (xx - 1) * n + yy);
            }
        }
    }
}

int main(){
    fin >> n >> q;
    for (int i = 1; i <= n; ++i){
        for (int j = 1; j <= n; ++j){
            fin >> mat[i][j];
        }
    }
    normalize();
    for (int i = 1; i <= n; ++i){
        for (int j = 1; j <= n; ++j){
            maxim = max(maxim, mat[i][j]);
            G[mat[i][j]].push_back({i, j});
            t[(i - 1) * n + j] = (i - 1) * n + j;
        }
    }
    for (int i = 1; i <= q; ++i){
        fin >> A[i] >> B[i] >> C[i] >> D[i];
        L[i] = 1;
        R[i] = maxim;
    }
    for (int l = 1; l <= maxim; l = l * 2){
        Clear();
        for (int i = 1; i <= q; ++i){
            if (L[i] <= R[i]){
                int mid = (L[i] + R[i]) / 2;
                Event[mid].push_back(i);
            }
        }
        for (int i = maxim; i >= 1; --i){
            Apply(i);
            for (auto it : Event[i]){
                int nod1 = (A[it] - 1) * n + B[it];
                int nod2 = (C[it] - 1) * n + D[it];
                if (GetParent(nod1) == GetParent(nod2)){
                    L[it] = i + 1;
                    ans[it] = i;
                }
                else{
                    R[it] = i - 1;
                }
            }
        }
    }
    for (int i = 1; i <= q; ++i){
        fout << mpInv[ans[i]] << "\n";
    }
    fin.close();
    fout.close();
    return 0;
}