Cod sursa(job #2755538)

Utilizator GabiTulbaGabi Tulba-Lecu GabiTulba Data 27 mai 2021 16:39:26
Problema Matrice 2 Scor 45
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.07 kb
#include <bits/stdc++.h>

#define MaxN 303
#define MaxQ 20003

using namespace std;

struct query {
    int a, b, poz;
};

int n, nrq, hmax, Next;
int mat[MaxN][MaxN];
pair<int, int> nod[MaxN * MaxN];
vector<int> G[MaxN * MaxN];
int ans[MaxQ];
int comp[MaxN * MaxN];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
queue<pair<pair<int, int>, vector<query>>> q;
vector<query> Q;

inline bool inside(int x, int y) {
    return x >= 1 && y >= 1 && x <= n && y <= n;
}

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

inline void Reinit() {
    Next = 1;
    for (int i = 1; i <= n * n; i++) {
        comp[i] = i;
    }
}

inline int Find(int x) {
    int root = x;
    while (root != comp[root]) {
        root = comp[root];
    }

    while (x != root) {
        int aux = comp[x];
        comp[x] = root;
        x = aux;
    }

    return root;
}

inline void add(int x) {
    for (int i = 0; i < G[x].size(); i++) {
        comp[Find(x)] = Find(G[x][i]);
    }
}

int main() {
    freopen("matrice2.in", "r", stdin);
    freopen("matrice2.out", "w", stdout);

    scanf("%d %d", &n, &nrq);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            scanf("%d", &mat[i][j]);
            hmax = max(hmax, mat[i][j]);
            nod[poz(i, j)] = {mat[i][j], poz(i, j)};
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            for (int dir = 0; dir < 4; dir++) {
                int newx = i + dx[dir];
                int newy = j + dy[dir];
                if (inside(newx, newy) && mat[newx][newy] >= mat[i][j]) {
                    G[poz(i, j)].push_back(poz(newx, newy));
                }
            }
        }
    }

    for (int i = 1; i <= nrq; i++) {
        int a, b, x, y;
        scanf("%d %d %d %d", &a, &b, &x, &y);
        Q.push_back({poz(a, b), poz(x, y), i});
    }
    sort(nod + 1, nod + 1 + n * n);
    reverse(nod + 1, nod + 1 + n * n);
    Reinit();
    q.push({{1, hmax}, Q});
    Next = 1;
    while (!q.empty()) {
        int l = q.front().first.second;
        int r = q.front().first.first;
        vector<query> Left;
        vector<query> Right;
        int mid = (l + r) / 2;
        if (nod[Next].first < mid) {
            Reinit();
        }

        while (nod[Next].first > mid) {
            add(nod[Next].second);
            Next++;
        }

        for (int i = 0; i < q.front().second.size(); i++) {
            query x = q.front().second[i];

            if (Find(x.a) == Find(x.b)) {
                Left.push_back(x);
            } else {
                Right.push_back(x);
            }
        }
        if (l - r < 2) {
            for (auto x : Left) {
                ans[x.poz] = l;
            }
            for (auto x : Right) {
                ans[x.poz] = r;
            }
        } else {
            if (!Left.empty()) {
                q.push({{mid + 1, l}, Left});
            }
            if (!Right.empty()) {
                q.push({{r, mid}, Right});
            }
        }
        q.pop();
    }
    for (int i = 1; i <= nrq; i++)
        printf("%d\n", ans[i]);

    return 0;
}