Cod sursa(job #2922108)

Utilizator nhphucqtNguyen Hoang Phuc nhphucqt Data 4 septembrie 2022 07:36:22
Problema Matrice 2 Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.43 kb
// dungeon sub 4 - parallel binary search (for loop) + dsu (fastio) (pragma)
// O((n^2 + q) * 20)

#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;

template<typename T>
inline void read(T &x) {
    char c;
    for (c = getchar(); !isdigit(c); c = getchar());
    x = c-'0';
    for (c = getchar(); isdigit(c); c = getchar())
        x = x*10 + (c-'0');
}

template<typename T>
inline void write(T x) {
    T tmp = x/10, de = 1;
    while (tmp > 0) { de *= 10; tmp /= 10; }
    while (de > 0) { putchar(x/de+'0'); x %= de; de /= 10; }
}

template<typename T>
inline void writeln(T x) {
    write(x);
    putchar('\n');
}

const int N = 507;
const int QUERY = 4e5+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() {
    freopen("matrice2.inp", "r", stdin);
    freopen("matrice2.out", "w", stdout);

    read(n);
    read(q);
    for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
        read(a[i][j]);
    }
    for (int i = 1; i <= q; ++i) {
        int x, y, u, v;
        read(x); read(y);
        read(u); read(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)
        writeln(ans[i]);

    return 0;
}