Cod sursa(job #2920295)

Utilizator nhphucqtNguyen Hoang Phuc nhphucqt Data 23 august 2022 15:09:43
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.19 kb
// Dungeon

/* Gợi ý giới hạn
1 <= a[i][j] <= 1e6
Sub1: n <= 50, q <= 10
Sub2: n <= 100, q <= 100 (có thể bỏ)
Sub3: n <= 200, q <= 1000
Sub4: n <= 300, q <= 1e5
Sub5: n <= 500, q <= 1e6
*/

// nhánh cận các thứ, cố gắng code các sub tối ưu nhất có thể (tránh code sub nhỏ ăn sub lớn)
// bò: dfs giới hạn lần chạy (vd: 100 lần) nếu chưa đến đích out ra false (có thể sai)
// bò: ngắt dijkstra nếu gặp đích (có thể sai)
// thử code cách cnp song song sử dụng dfs/bfs thay dsu (tle)

#include <bits/stdc++.h>

using namespace std;

struct Query {
    int x, y, u, v, id;
};

const int D[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
const int N = 307;
const int Q = 2e4+7;
int n, q, a[N][N];
Query ques[Q];

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

const int NODE = N*N;
const int EDGE = NODE*2;
struct Edge {
    int x, y, w;
    Edge() {}
    Edge(int _x, int _y, int _w) {
        x = _x; y = _y; w = _w;
    }
};

int numNode, numEdge, numEvent;
pair<int,int> newQues[Q];
Edge edges[EDGE];
int fa[NODE];
int ans[Q], curId[Q], lef[Q], rig[Q];

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);
}

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) {
        cin >> ques[i].x >> ques[i].y >> ques[i].u >> ques[i].v;
        ques[i].id = i;
    }

    for (int i = 1; i <= q; ++i) {
        newQues[i].first = getId(ques[i].x,ques[i].y);
        newQues[i].second = getId(ques[i].u,ques[i].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;
    });
    
    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(newQues[curId[i]].first,newQues[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;
}