https://codeforces.com/group/NVaJtLaLjS/contest/253993/attachments
題意:
n*m個點,每個點有一個高度,q個詢問,每次問兩點之間最小的路徑最大值。
思路:把表格看成一張圖,和洛谷P1967是一樣的。https://blog.csdn.net/Wen_Yongqi/article/details/101546392
都是無向圖+詢問多次兩點間距離最大(小)的最小(大)值,用mst+lca解決。
#include<bits/stdc++.h>
using namespace std;
int n,m,q,cnt;
int a[505][505];
int x[1000000],y[1000000],z[1000000];
int p[300000],e[1000000];
vector<int> G[300000];
struct Edge{
int from,to,dist;
};
vector<Edge> edges;
int fa[300000][20],maxcost[300000][20],deep[300000],vis[300000];
int findset(int x){return x==p[x]?x:p[x]=findset(p[x]);}
bool cmp(int a,int b){return z[a]<z[b];}
void AddEdge(int x,int y,int z)
{
edges.push_back((Edge){x,y,z});
edges.push_back((Edge){y,x,z});
G[x].push_back(edges.size()-2);
G[y].push_back(edges.size()-1);
}
void dfs(int u,int f,int d)
{
vis[u]=1;
for(int i=0;i<G[u].size();i++)
{
Edge& e=edges[G[u][i]];
int v=e.to,w=e.dist;
if(v==f || vis[v])continue;
fa[v][0]=u;
maxcost[v][0]=w;
deep[v]=d+1;
dfs(v,u,d+1);
}
}
void lca_init()
{
for(int i=0;i<n*m;i++)for(int j=1;(1<<j)<n*m;j++)fa[i][j]=-1;
for(int j=1;(1<<j)<n*m;j++)
for(int i=0;i<n*m;i++)
if(fa[i][j-1]!=-1)
{
int a=fa[i][j-1];
fa[i][j]=fa[a][j-1];
maxcost[i][j]=max(maxcost[i][j-1],maxcost[a][j-1]);
}
}
int query(int p,int q)
{
int log;
if(deep[p]<deep[q])swap(p,q);
for(log=1;(1<<log)<=deep[p];log++);
log--;
int ans=-(1<<30);
for(int i=log;i>=0;i--)
if(deep[p]-(1<<i)>=deep[q])
{
ans=max(ans,maxcost[p][i]);
p=fa[p][i];
}
if(p==q)return ans; //lca爲p或q
for(int i=log;i>=0;i--)
if(fa[p][i]!=-1 && fa[p][i]!=fa[q][i])
{
ans=max(ans,maxcost[p][i]);
p=fa[p][i];
ans=max(ans,maxcost[q][i]);
q=fa[q][i];
}
ans=max(ans,maxcost[p][0]);
ans=max(ans,maxcost[q][0]);
return ans;//lca爲fa[p]或fa[q]
}
int main()
{
///freopen("input.in","r",stdin);
cin>>n>>m>>q;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&a[i][j]),p[i*m+j]=i*m+j;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(i!=0)
{
cnt++;
x[cnt]=i*m+j;y[cnt]=(i-1)*m+j;z[cnt]=max(a[i][j],a[i-1][j]);
}
if(i!=n-1)
{
cnt++;
x[cnt]=i*m+j;y[cnt]=(i+1)*m+j;z[cnt]=max(a[i][j],a[i+1][j]);
}
if(j!=0)
{
cnt++;
x[cnt]=i*m+j;y[cnt]=i*m+j-1;z[cnt]=max(a[i][j],a[i][j-1]);
}
if(j!=m-1)
{
cnt++;
x[cnt]=i*m+j;y[cnt]=i*m+j+1;z[cnt]=max(a[i][j],a[i][j+1]);
}
}
for(int i=1;i<=cnt;i++)e[i]=i;
sort(e+1,e+1+cnt,cmp);
for(int i=1;i<=cnt;i++)
{
int a=x[e[i]],b=y[e[i]],c=z[e[i]];
int a2=findset(a),b2=findset(b);
if(a2!=b2)
{
p[a2]=b2;
AddEdge(a,b,c);
}
}
deep[0]=0;
fa[0][0]=-1;
dfs(0,-1,0);
lca_init();
int x1,y1,x2,y2,u,v;
while(q--)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1--;y1--;x2--;y2--;
u=x1*m+y1;v=x2*m+y2;
if(u==v)printf("%d\n",a[x1][y1]);
else printf("%d\n",query(u,v));
}
return 0;
}