Cod sursa(job #2591813)

Utilizator IulianOleniucIulian Oleniuc IulianOleniuc Data 31 martie 2020 13:16:29
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.24 kb
#include <bits/stdc++.h>
using namespace std;

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

class Forest {
  private:
    vector<int> height, father, ans, ind;
    vector<set<int>> qry;

    void merge(int x, int y, int val) {
        if (qry[ind[x]].size() > qry[ind[y]].size()) {
            for (int it : qry[ind[y]])
                if (qry[ind[x]].find(it) == qry[ind[x]].end())
                    qry[ind[x]].insert(it);
                else {
                    ans[it] = val;
                    qry[ind[x]].erase(it);
                }
        }
        else {
            for (int it : qry[ind[x]])
                if (qry[ind[y]].find(it) == qry[ind[y]].end())
                    qry[ind[y]].insert(it);
                else {
                    ans[it] = val;
                    qry[ind[y]].erase(it);
                }
            ind[x] = ind[y];
        }
    }

  public:
    Forest(int n, int q) :
        height(n + 1), father(n + 1),
        ans(q), ind(n + 1), qry(n + 1) {
            for (int i = 1; i <= n; i++)
                ind[i] = i;
        }

    int find(int x) {
        int root = x;
        while (father[root])
            root = father[root];
        int aux;
        while (father[x]) {
            aux = father[x];
            father[x] = root;
            x = aux;
        }
        return root;
    }

    void unite(int x, int y, int val) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX == rootY)
            return;
        if (height[rootX] < height[rootY]) {
            merge(rootY, rootX, val);
            father[rootX] = rootY;
        }
        else {
            merge(rootX, rootY, val);
            father[rootY] = rootX;
            if (height[rootX] == height[rootY])
                height[rootX]++;
        }
    }

    void addQuery(int x, int y) {
        static int id = 0;
        qry[x].insert(id);
        qry[y].insert(id);
        id++;
    }

    vector<int> solve() {
        return ans;
    }
};

int main() {
    int n, q; fin >> n >> q;
    vector<vector<int>> mat(n + 1, vector<int>(n + 1));
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            fin >> mat[i][j];

    auto id = [&](int x, int y) {
        return (x - 1) * n + y;
    };
    auto in = [&](int x, int y) {
        return 1 <= x && x <= n
            && 1 <= y && y <= n;
    };

    Forest dsu(n * n, q);
    for (int i = 0; i < q; i++) {
        int x1, y1, x2, y2; fin >> x1 >> y1 >> x2 >> y2;
        dsu.addQuery(id(x1, y1), id(x2, y2));
    }

    vector<tuple<int, int, int>> cells;
    cells.reserve(n * n);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            cells.emplace_back(mat[i][j], i, j);
    sort(cells.rbegin(), cells.rend());

    const int addLin[] = {-1, 0, 1, 0};
    const int addCol[] = {0, 1, 0, -1};

    for (auto cell : cells) {
        int x1, y1, val; tie(val, x1, y1) = cell;
        for (int i = 0; i < 4; i++) {
            int x2 = x1 + addLin[i];
            int y2 = y1 + addCol[i];
            if (in(x2, y2) && mat[x2][y2] >= mat[x1][y1])
                dsu.unite(id(x1, y1), id(x2, y2), val);
        }
    }

    auto ans = dsu.solve();
    for (int i = 0; i < q; i++)
        fout << ans[i] << '\n';

    fout.close();
    return 0;
}