Cod sursa(job #2591801)

Utilizator IulianOleniucIulian Oleniuc IulianOleniuc Data 31 martie 2020 12:51:57
Problema Matrice 2 Scor 65
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3 kb
#include <bits/stdc++.h>
using namespace std;

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

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

    void merge(int x, int y, int val) {
        vector<int> arr;
        qry[x].push_back(1e9);
        qry[y].push_back(1e9);
        for (int i = 0, j = 0; qry[x][i] < 1e9 || qry[y][j] < 1e9; )
            if (qry[x][i] < qry[y][j])
                arr.push_back(qry[x][i++]);
            else if (qry[x][i] > qry[y][j])
                arr.push_back(qry[y][j++]);
            else {
                ans[qry[x][i]] = val;
                i++; j++;
            }
        qry[x].clear();
        qry[y].clear();
        qry[x] = arr;
    }

  public:
    Forest(int n, int q) :
        ans(q), height(n + 1), father(n + 1), qry(n + 1) { }

    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].push_back(id);
        qry[y].push_back(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;
}