Cod sursa(job #3040163)

Utilizator tibinyteCozma Tiberiu-Stefan tibinyte Data 29 martie 2023 13:55:46
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.2 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("matrice2.in");
ofstream fout("matrice2.out");

const int lgmax = 20;
const vector<int> dx = {1, -1, 0, 0};
const vector<int> dy = {0, 0, 1, -1};

struct deseu
{
    vector<int> par;
    vector<int> sz;
    void resize(int n)
    {
        par = vector<int>(n + 1);
        sz = vector<int>(n + 1);
    }
    void make_set(int x)
    {
        par[x] = x;
        sz[x] = 1;
    }
    int find_set(int x)
    {
        if (par[x] == x)
        {
            return x;
        }
        return par[x] = find_set(par[x]);
    }
    void unite(int a, int b)
    {
        a = find_set(a);
        b = find_set(b);
        if (a != b)
        {
            if (sz[a] > sz[b])
            {
                swap(a, b);
            }
            par[a] = b;
            sz[b] += sz[a];
        }
    }
};

struct query
{
    int ans;
    int x1;
    int y1;
    int x2;
    int y2;
    int ind;
    bool operator<(query b) const
    {
        return ans > b.ans;
    }
};

int32_t main()
{
    cin.tie(nullptr)->sync_with_stdio(false);
    int n, q;
    fin >> n >> q;
    vector<vector<int>> a(n + 1, vector<int>(n + 1));

    vector<tuple<int, int, int>> pozitii;

    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= n; ++j)
        {
            fin >> a[i][j];
            pozitii.push_back({a[i][j], i, j});
        }
    }

    sort(pozitii.begin(), pozitii.end(), greater<tuple<int, int, int>>());

    vector<query> queries(q + 1);
    for (int i = 1; i <= q; ++i)
    {
        int x1, y1, x2, y2;
        fin >> x1 >> y1 >> x2 >> y2;
        queries[i] = {0, x1, y1, x2, y2, i};
    }


    for (int bit = lgmax; bit >= 0; --bit)
    {
        sort(queries.begin() + 1, queries.end());
        int p = 0;
        deseu tree;
        tree.resize(n * n);

        for (int i = 1; i <= n * n; ++i)
        {
            tree.make_set(i);
        }

        vector<vector<int>> works(n + 1, vector<int>(n + 1));

        function<void(int, int)> add = [&](int i, int j)
        {
            for (int k = 0; k < 4; ++k)
            {
                int cx = i + dx[k];
                int cy = j + dy[k];
                if (cx >= 1 && cx <= n && cy >= 1 && cy <= n && works[cx][cy])
                {
                    tree.unite((i - 1) * n + j, (cx - 1) * n + cy);
                }
            }
        };

        for (int i = 1; i <= q; ++i)
        {
            while (p < (int)pozitii.size() && get<0>(pozitii[p]) >= queries[i].ans + (1 << bit))
            {
                works[get<1>(pozitii[p])][get<2>(pozitii[p])] = 1;
                add(get<1>(pozitii[p]), get<2>(pozitii[p]));
                p++;
            }

            if (tree.find_set((queries[i].x1 - 1) * n + queries[i].y1) == tree.find_set((queries[i].x2 - 1) * n + queries[i].y2))
            {
                queries[i].ans += (1 << bit);
            }
        }
    }
    vector<int> rep(q + 1);
    for (int i = 1; i <= q; ++i)
    {
        rep[queries[i].ind] = queries[i].ans;
    }
    for (int i = 1; i <= q; ++i)
    {
        fout << rep[i] << '\n';
    }
}