Pagini recente » Cod sursa (job #1652595) | Cod sursa (job #2403963) | Cod sursa (job #2882831) | Cod sursa (job #1232809) | Cod sursa (job #1825520)
#include <fstream>
#include <algorithm>
using namespace std;
class InputReader {
public:
InputReader() {}
InputReader(const char *file_name) {
input_file = fopen(file_name, "r");
cursor = 0;
fread(buffer, SIZE, 1, input_file);
}
inline InputReader &operator >>(int &n) {
while(buffer[cursor] < '0' || buffer[cursor] > '9') {
advance();
}
n = 0;
while('0' <= buffer[cursor] && buffer[cursor] <= '9') {
n = n * 10 + buffer[cursor] - '0';
advance();
}
return *this;
}
private:
FILE *input_file;
static const int SIZE = 1 << 17;
int cursor;
char buffer[SIZE];
inline void advance() {
++ cursor;
if(cursor == SIZE) {
cursor = 0;
fread(buffer, SIZE, 1, input_file);
}
}
};
const int NMAX = 300 + 5;
int father[2 * NMAX * NMAX];
int h[2 * NMAX * NMAX];
int cost[2 * NMAX * NMAX];
int ancestor[2 * NMAX * NMAX];
void init(int lim) {
for (int i = 1; i <= lim; ++ i)
father[i] = i, ancestor[i] = i, h[i] = 0;
}
int find(int node) {
if (father[node] != father[father[node]])
father[node] = find(father[node]);
return father[node];
}
vector <int> tree[2 * NMAX * NMAX];
int nodes;
void unite1(int a, int b, int val) {
a = find(a), b = find(b);
if (a == b)
return ;
++ nodes;
tree[nodes].push_back(ancestor[a]);
tree[nodes].push_back(ancestor[b]);
cost[nodes] = val;
if (h[a] < h[b]) {
father[a] = b;
ancestor[b] = nodes;
}
else {
if (h[a] == h[b])
++ h[a];
father[b] = a;
ancestor[a] = nodes;
}
return ;
}
void unite2(int a, int b) {
a = find(a), b = find(b);
if (a == b)
return ;
if (h[a] < h[b])
father[a] = b;
else {
if (h[a] == h[b])
++ h[a];
father[b] = a;
}
return ;
}
int n;
int mat[NMAX][NMAX];
int encode(int lin, int col) {
return (lin - 1) * n + col;
}
void addCell(int lin, int col, int val) {
static const int dLin[] = {0, 0, 1, -1};
static const int dCol[] = {1, -1, 0, 0};
for (int k = 0; k < 4; ++ k) {
int nLin = lin + dLin[k];
int nCol = col + dCol[k];
if (nLin >= 1 && nCol >= 1 && nLin <= n && nCol <= n && mat[nLin][nCol] >= mat[lin][col])
unite1(encode(nLin, nCol), encode(lin, col), val);
}
}
vector <pair <int, pair <int, int > > > cells;
int first[2 * NMAX * NMAX];
int firstSz;
void dfs(int node) {
first[node] = ++ firstSz;
for (auto it: tree[node]) {
//father[it] = node;
//h[it] = 1 + h[node];
dfs(it);
}
}
int bruteLca(int a, int b) {
while (a != b) {
if (h[a] > h[b])
a = father[a];
else
b = father[b];
}
return a;
}
vector <pair <int, int> > queries[NMAX * NMAX];
const int QMAX = 20000 + 5;
int ans[QMAX];
void TarjanLca(int node) {
for (auto it: tree[node]) {
TarjanLca(it);
unite2(node, it);
ancestor[find(node)] = node;
}
if (node <= n * n)
for (auto it: queries[node])
ans[it.second] = cost[ancestor[find(it.first)]];
}
int main()
{
InputReader cin("matrice2.in");
ofstream cout("matrice2.out");
int q = 0;
cin >> n >> q;
for (int i = 1; i <= n; ++ i)
for (int j = 1; j <= n; ++ j)
cin >> mat[i][j];
for (int i = 1; i <= n; ++ i)
for (int j = 1; j <= n; ++ j)
cells.push_back({-mat[i][j], {i, j}});
sort(cells.begin(), cells.end());
nodes = n * n;
init(2 * nodes);
for (auto it: cells)
addCell(it.second.first, it.second.second, -it.first);
dfs(nodes);
for (int i = 1; i <= q; ++ i) {
int l1, c1, l2, c2;
cin >> l1 >> c1;
cin >> l2 >> c2;
int a = encode(l1, c1);
int b = encode(l2, c2);
if (first[a] > first[b])
swap(a, b);
queries[b].push_back(make_pair(a, i));
}
init(nodes);
TarjanLca(nodes);
for (int i = 1; i <= q; ++ i)
cout << ans[i] << '\n';
return 0;
}