解题报告:
最大值最小的路径肯定在MST上面,那么我们直接求一个MST然后就是任意两点之间的树上路径最小值即可。
树上倍增即可。但是要注意同一个点的情况。
#include<bits/stdc++.h>
#define LL long long
#define pii pair<LL,int>
#define all(x) x.begin(),x.end()
#define wp(x) write(x),putchar('\n')
#define wpl(x) write(x),putchar(' ')
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 500 + 5;
const int MOD = 998244353;
inline int read() {
int s = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {s = (s << 1) + (s << 3) + ch - '0'; ch = getchar();}
return s * f;
}
inline void write(LL x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
struct node{
int x,y,w;
node(){}
node(int _x,int _y,int _w){x=_x;y=_y;w=_w;}
bool operator < (const node &ls) const {return ls.w>w;}
}p[maxn*maxn<<2];
struct TMD{
int to,next,w;
TMD(){}
TMD(int _to,int _next,int _w){to=_to,next=_next;w=_w;}
}edge[maxn*maxn<<2];
int head[maxn*maxn],knt,pre[maxn*maxn][25],Max[maxn*maxn][25],deep[maxn*maxn];
int f[maxn*maxn],mp[maxn][maxn];
void add(int from,int to,int w) {edge[++knt]={to,head[from],w};head[from]=knt;}
int getfind(int x) {return x==f[x]?x:f[x]=getfind(f[x]);}
void dfs(int now,int fa){
deep[now]=deep[fa]+1;pre[now][0]=fa;
for(int i=1;i<20;i++){
pre[now][i]=pre[pre[now][i-1]][i-1];
Max[now][i]=max(Max[now][i-1],Max[pre[now][i-1]][i-1]);
}
for(int i=head[now];i;i=edge[i].next){
int to=edge[i].to,w=edge[i].w;
if(to==fa) continue;
Max[to][0]=w;
dfs(to,now);
}
}
int query(int x,int y){
int ans=0;
if(deep[x]<deep[y]) swap(x,y);
for(int i=19;i>=0;i--){
if(deep[pre[x][i]]>=deep[y]){
ans=max(ans,Max[x][i]);
x=pre[x][i];
}
}
if(x==y) return ans;
for(int i=19;i>=0;i--){
if(pre[x][i]!=pre[y][i]){
ans=max(ans,max(Max[x][i],Max[y][i]));
x=pre[x][i];y=pre[y][i];
}
}
ans=max(ans,max(Max[y][0],Max[x][0]));
return ans;
}
int main() {
int n=read(),m=read(),q=read(),cnt=0,x1,y1,x2,y2,tp1,tp2;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) mp[i][j]=read();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i<n) p[++cnt]=node((i-1)*m+j,i*m+j,max(mp[i][j],mp[i+1][j]));
if(j<m) p[++cnt]=node((i-1)*m+j,(i-1)*m+j+1,max(mp[i][j],mp[i][j+1]));
}
}
sort(p+1,p+cnt+1);
for(int i=1;i<=n*m;i++) f[i]=i;
int sum=1,k1,k2;
for(int i=1;i<=cnt;i++){
k1=getfind(p[i].x);k2=getfind(p[i].y);
if(k1!=k2){
f[k2]=k1;sum++;
add(p[i].x,p[i].y,p[i].w);
add(p[i].y,p[i].x,p[i].w);
}
if(sum==n*m) break;
}
dfs(1,0);
for(int i=1;i<=q;i++){
x1=read(),y1=read();x2=read(),y2=read();
tp1=(x1-1)*m+y1;tp2=(x2-1)*m+y2;
wp(max(query(tp1,tp2),max(mp[x1][y1],mp[x2][y2])));
}
return 0;
}