Cod sursa(job #2920406)

Utilizator nhphucqtNguyen Hoang Phuc nhphucqt Data 24 august 2022 09:36:49
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.9 kb
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("omit-frame-pointer")
#pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>

using namespace std;

const int N = 407;
const int QUERY = 3e5+7;
const int NODE = N*N;
const int EDGE = NODE*2;
int n, q, a[N][N];
pair<int,int> ques[QUERY];

int getId(int x, int y) {
    return (x-1) * n + y;
}

struct Edge {
    int x, y, w;
    Edge() {}
    Edge(int _x, int _y, int _w) {
        x = _x; y = _y; w = _w;
    }
};

int numNode, numEdge;
Edge edges[EDGE];
int fa[NODE];
int ans[QUERY], curId[QUERY], lef[QUERY], rig[QUERY];

int root(int x) {
    return fa[x] < 0 ? x : fa[x] = root(fa[x]);
}

void Unite(int u, int v) {
    u = root(u);
    v = root(v);
    if (u == v) return;
    if (fa[u] > fa[v]) swap(u,v);
    fa[u] += fa[v];
    fa[v] = u;
}

bool sameComp(int x, int y) {
    return root(x) == root(y);
}

void filter() {
    memset(fa, -1, (numNode+1) * sizeof(int));
    int newNum = 0;
    for (int i = 0; i < numEdge; ++i) {
        int u = root(edges[i].x);
        int v = root(edges[i].y);
        if (u != v) {
            Unite(u, v);
            edges[newNum++] = edges[i];
        }
    }
    numEdge = newNum;
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    freopen("matrice2.in", "r", stdin);
    freopen("matrice2.out", "w", stdout);

    cin >> n >> q;
    for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
        cin >> a[i][j];
    }
    for (int i = 1; i <= q; ++i) {
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        ques[i].first = getId(x,y);
        ques[i].second = getId(u,v);
    }
    numNode = n * n;
    numEdge = 0;
    for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
        if (i < n)
            edges[numEdge++] = Edge(getId(i,j), getId(i+1,j), min(a[i][j],a[i+1][j]));
        if (j < n)
            edges[numEdge++] = Edge(getId(i,j), getId(i,j+1), min(a[i][j],a[i][j+1]));
    }
    sort(edges,edges+numEdge,[&](const Edge &a, const Edge &b) {
        return a.w > b.w;
    });
    
    filter();
    for (int i = 1; i <= q; ++i) {
        ans[i] = 0;
        curId[i] = i;
    }
    for (int add = (1<<20); add >= 1; add>>=1) {
        memset(fa, -1, (numNode+1) * sizeof(int));
        int numLef = 0, numRig = 0;
        for (int i = 1, j = 0; i <= q; ++i) {
            while (j < numEdge && edges[j].w >= ans[curId[i]]+add) {
                Unite(edges[j].x,edges[j].y);
                j++;
            }
            if (sameComp(ques[curId[i]].first,ques[curId[i]].second)) {
                ans[curId[i]] |= add;
                rig[numRig++] = curId[i];
            }
            else {
                lef[numLef++] = curId[i];
            }
        }
        merge(lef,lef+numLef,rig,rig+numRig,curId+1,[&](int x, int y) {
            return ans[x] > ans[y];
        });
    }
    for (int i = 1; i <= q; ++i)
        cout << ans[i] << '\n';

    return 0;
}