题解:P11065 【MX-X4-T5】「Jason-1」占领高地
一个暴力的想法是对于每一个补给站
考虑去除不优的边,减少边的数量。首先不难观察到一个结论:若点
于是不难想到将该图简化为相邻方格内连边,需要对于每一个相邻的方格,求得覆盖他们两个的补给站的
观察满足被补给站
对于相邻两个格子
对建出来的新图跑最大生成树,然后建立 Kruskal 重构树即可。复杂度
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define repp(i,j,k) for(int i=j;i>=k;i--)
#define ls(x) (x<<1)
#define rs(x) ((x<<1)|1)
#define mp make_pair
#define sec second
#define fir first
#define pii pair<int,int>
#define lowbit(i) i&-i
#define int long long
#define qingbai 666
using namespace std;
typedef long long ll;
const int N=305,M=2e5+5,S=(1<<15)+5,inf=(ll)1e18+7,mo=998244353;
void read(int &p){
int x=0,w=1;
char ch=0;
while(!isdigit(ch)){
if(ch=='-')w=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
p=x*w;
}
int n,m,q;
int h[N][N],p[N][N],f[N][N][10];
int maxh[N][N],maxl[N][N];
int fa[N*N*2][20],dep[N*N*2];
struct edge{
int x,y,val;
friend bool operator<(edge x,edge y){
return x.val>y.val;
}
}e[N*N*2];
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1},cnte;
void update(int x,int y,int op){
int lx=x+dx[op],ly=y+dy[op];
repp(k,9,0){
int nwk=k+h[lx][ly]-h[x][y]-1;
if(nwk<0)break;
f[x][y][nwk]=max(f[x][y][nwk],f[lx][ly][k]);
}
}
void getedge(int k){
rep(i,1,n-1){
rep(j,1,m){
if(k+h[i][j]-h[i+1][j]-1>=0)maxl[i][j]=max(maxl[i][j],f[i][j][k]);
if(k+h[i+1][j]-h[i][j]-1>=0)maxl[i][j]=max(maxl[i][j],f[i+1][j][k]);
}
}
rep(i,1,n){
rep(j,1,m-1){
if(k+h[i][j]-h[i][j+1]-1>=0)maxh[i][j]=max(maxh[i][j],f[i][j][k]);
if(k+h[i][j+1]-h[i][j]-1>=0)maxh[i][j]=max(maxh[i][j],f[i][j+1][k]);
}
}
}
int getid(int x,int y){
return (x-1)*m+y;
}
struct bcj{
int fa[N*N*2];
void init(){
rep(i,1,n*m*2)
fa[i]=i;
}
int find(int x){
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
bool merge(int x,int y){
x=find(x),y=find(y);
if(x==y)return 0;
fa[x]=y;
return 1;
}
}B;
int val[N*N*2],cntn;
vector<int>et[N*N*2];
void dfs(int x,int f){
dep[x]=dep[f]+1,fa[x][0]=f;
rep(i,1,18)
fa[x][i]=fa[fa[x][i-1]][i-1];
for(auto j:et[x])
dfs(j,x);
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
repp(i,18,0)
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
repp(i,18,0)
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int nrt[N*N*2];
signed main(){
read(n),read(m),read(q);
rep(i,1,n){
rep(j,1,m)
read(h[i][j]);
}
rep(i,1,n){
rep(j,1,m)
read(p[i][j]);
}
rep(i,1,n){
rep(j,1,m){
rep(k,0,9)
f[i][j][k]=-inf;
maxh[i][j]=maxl[i][j]=-inf;
}
}
rep(i,1,n){
rep(j,1,m)
f[i][j][p[i][j]]=h[i][j];
}
rep(i,2,n){
rep(j,1,m)
update(i,j,0);
}
repp(i,n-1,1){
rep(j,1,m)
update(i,j,1);
}
rep(i,1,n){
rep(j,2,m)
update(i,j,2);
}
rep(i,1,n){
repp(j,m-1,1)
update(i,j,3);
}
rep(k,0,9)
getedge(k);
rep(i,1,n){
rep(j,1,m){
if(j!=m)e[++cnte]=(edge){getid(i,j),getid(i,j+1),maxh[i][j]};
if(i!=n)e[++cnte]=(edge){getid(i,j),getid(i+1,j),maxl[i][j]};
}
}
sort(e+1,e+cnte+1);
B.init();
cntn=n*m;
rep(i,1,cnte){
int x=e[i].x,y=e[i].y;
x=B.find(x),y=B.find(y);
if(x==y)continue;
val[++cntn]=e[i].val;
B.merge(x,cntn);
B.merge(y,cntn);
et[cntn].push_back(x),et[cntn].push_back(y);
}
dfs(cntn,0);
while(q--){
int a,b,x,y;
read(a),read(b),read(x),read(y);
y=getid(x,y),x=getid(a,b);
printf("%lld\n",max(-1ll,val[lca(x,y)]));
}
return 0;
}