Cod sursa(job #2591803)

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

class Parser {
  private:
    vector<char> str;
    int ptr;
    FILE *fin;

    char getChar() {
        if (ptr == (int) str.size()) {
            fread(str.data(), sizeof(char), str.size(), fin);
            ptr = 0;
        }
        return str[ptr++];
    }

    template<class T>
    T getInt() {
        char chr = getChar();
        while (!isdigit(chr) && chr != '-')
            chr = getChar();
        int sgn = +1;
        if (chr == '-') {
            sgn = -1;
            chr = getChar();
        }
        T nr = 0;
        while (isdigit(chr)) {
            nr = nr * 10 + chr - '0';
            chr = getChar();
        }
        return nr * sgn;
    }

  public:
    Parser(const char* name) : str(1e5), ptr(str.size()), fin(fopen(name, "r")) { }
    ~Parser() { fclose(fin); }

    template<class T>
    friend Parser& operator>>(Parser& in, T& nr) {
        nr = in.getInt<T>();
        return in;
    }
};

Parser 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;
}