题意:每个点一个权值,q个询问,每次询问从一点到另一点的路径经过的最小的最大值。
思路:建图,每个点和相邻的点都连上边,如果构成了一个环,那么删掉环中权值最大的边一定对答案无影响,所以最后建成的是一棵树,用最小生成树的方式建树即可。询问时求两点LCA过程中得出最大值。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
typedef pair<int, int> P;
const int maxn = 3e5+5;
struct Edge{
int u, v, w;
bool operator < (const Edge & e) const {
return w < e.w;
}
}edge[maxn<<1];
int n, m, q, tot;
int fa[maxn], v[maxn], val[maxn];
std::vector<P> e[maxn];
int Find(int x){return x == fa[x] ? x : fa[x] = Find(fa[x]);}
void Merge(int x, int y){
int fx = Find(x), fy = Find(y);
fa[fy] = fx;
}
int chg(int x, int y) {return x*m+y;}
void Build_Tree(){
for(int i=1; i<=tot; i++){
int u = edge[i].u, v = edge[i].v, w = edge[i].w;
if(Find(u) == Find(v)) continue;
Merge(u, v);
e[u].push_back(P(v, w)); e[v].push_back(P(u, w));
}
}
int d[maxn], f[maxn][21], Max[maxn][21];
void dfs2(int u, int fa){
d[u] = d[fa] + 1; f[u][0] = fa;
Max[u][0] = max(v[u], v[fa]);
for(int i=1; i<=20; i++){
f[u][i] = f[f[u][i-1]][i-1];
Max[u][i] = max(Max[u][i], max(Max[u][i-1], Max[f[u][i-1]][i-1]));
}
for(auto it : e[u]) if(it.first != fa) dfs2(it.first, u);
}
int lca(int u, int x){
int mx = max(v[u],v[x]);
if(d[u] > d[x]) swap(u, x);
for(int i=20; i>=0; i--)
if(d[u] <= d[x]-(1<<i))
mx = max(mx, Max[x][i]), x = f[x][i];
if(u == x) return mx; // u
for(int i=20; i>=0; i--){
if(f[u][i] != f[x][i])
mx = max(mx, max(Max[u][i], Max[x][i])), u = f[u][i], x = f[x][i];
}
// cout << u << " " << x << " " << mx << endl;
return max(mx, v[f[x][0]]); //f[u][0]
}
int main(){
for(int i=1; i<maxn; i++) fa[i] = i;
cin >> n >> m >> q;
for(int i=1; i<=n; ++i){
for(int j=1; j<=m; ++j)
cin >> v[chg(i, j)];
for(int j=1; j<=m; j++){
if(j<m) edge[++tot] = Edge{chg(i, j), chg(i, j+1), max(v[chg(i, j)], v[chg(i, j+1)])};
if(i > 1) edge[++tot] = Edge{chg(i-1, j), chg(i, j), max(v[chg(i-1,j)], v[chg(i, j)])};
}
}
sort(edge+1, edge+1+tot);
Build_Tree();
/*for(int i=1; i<=100; i++){
for(auto it : e[i]){
printf("%d*(%d,%d)--%d\n", v[i], i, it.first, it.second);
}
}*/
dfs2(chg(1, 1), chg(1, 1));
/* for(int i=1; i<=100; i++){
if(Max[i][0] == 0) continue;
cout << i << " " << Max[i][0] << " " << Max[i][1] << " " << Max[i][2] << endl;
}*/
int x1, y1, x2, y2;
while(q--){
cin >> x1 >> y1 >> x2 >> y2;
cout << lca(chg(x1, y1), chg(x2, y2)) << endl;
}
}
/*
2 3 3
1 3 2
2 4 5
*/