Cod sursa(job #2920286)

Utilizator nhphucqtNguyen Hoang Phuc nhphucqt Data 23 august 2022 14:28:34
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.14 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];
set<int> comp[NODE];
vector<int> query[NODE];

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

void Unite(int u, int v, int w) {
    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;
    for (int x : comp[v]) {
        for (int i = (int)query[x].size()-1; i >= 0; --i) {
            int id = query[x][i];
            int y = x ^ newQues[id].first ^ newQues[id].second;
            if (comp[u].count(y)) {
                ans[id] = w;
                query[x][i] = query[x].back();
                query[x].pop_back();
            }
        }
    }
    comp[u].insert(comp[v].begin(),comp[v].end());
    comp[v] = set<int>();
}

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;
    });
    
    memset(fa, -1, (numNode+1) * sizeof(int));
    for (int i = 1; i <= numNode; ++i) {
        comp[i].insert(i);
    }
    for (int i = 1; i <= q; ++i) {
        query[newQues[i].first].push_back(i);
        query[newQues[i].second].push_back(i);
    }
    for (int i = 0; i < numEdge; ++i) 
        Unite(edges[i].x, edges[i].y, edges[i].w);

    for (int i = 1; i <= q; ++i)
        cout << ans[i] << '\n';

    return 0;
}