lojnode
\((l,mid)(mid+1,r)\).考慮跨過mid的貢獻。c++
假設選的中間那條線的點爲gzy,貢獻爲\(dis(x,gzy)+dis(gzy,y)\)spa
那就計算n遍最短路,一次分治爲\(n^2mlog{nm}\)code
設S=n*m.矩陣的長度是不定的,每次取最長的邊進行分治是最好的,n最壞爲\(\sqrt{n}\)。get
\(f(n)=2*f(\frac{n}{2})+S\sqrt{S}logS。因此總的複雜度就是\)\(S\sqrt{S}logS\)it
都在同側的也須要跨一跨
代碼io
#include <bits/stdc++.h> #define FOR(i,a,b) for(int i=a;i<=b;++i) using namespace std; const int _=1e5+7,INF=0x3f3f3f3f; int read() { int x=0,f=1;char s=getchar(); for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1; for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0'; return x*f; } int n,m,q,ans[_],vis[_]; struct node { int x,y,X,Y,u,v,id; }Q[_],tmp[_]; bool cmp(node a,node b) {return a.id<b.id;} struct edge {int v,nxt,q;}e[_]; int head[_],tot; void add(int u,int v,int q) { e[++tot].v=v; e[tot].q=q; e[tot].nxt=head[u]; head[u]=tot; } int id(int x,int y) {return (x-1)*m+y;} struct T_T { int u,val; T_T(int a=0,int b=0) {u=a,val=b;} bool operator < (const T_T &b) const {return val>b.val;} }; int dis[_]; void dij(int S) { dis[S]=0; priority_queue<T_T> q; q.push(T_T(S,0)); while(!q.empty()) { T_T u=q.top();q.pop(); if(dis[u.u]!=u.val) continue; for(int i=head[u.u];i;i=e[i].nxt) { int v=e[i].v; if(vis[v]&&dis[v]>u.val+e[i].q) { dis[v]=u.val+e[i].q; q.push(T_T(v,dis[v])); } } } } void solve(int x,int y,int X,int Y,int l,int r) { if(l>r) return; if(x==X&&y==Y) { for(int i=l;i<=r;++i) ans[Q[i].id]=0; return; } if(Y-y>X-x) { int mid=(Y+y)>>1; FOR(i,x,X) { FOR(j,x,X) FOR(k,y,Y) dis[id(j,k)]=INF; dij(id(i,mid)); FOR(j,l,r) ans[Q[j].id]=min(dis[Q[j].u]+dis[Q[j].v],ans[Q[j].id]); } FOR(i,x,X) vis[id(i,mid)]=0; int p=l,q=r; FOR(i,l,r) { if(max(Q[i].y,Q[i].Y)<=mid) tmp[p++]=Q[i]; if(min(Q[i].y,Q[i].Y)>mid) tmp[q--]=Q[i]; } FOR(i,l,r) Q[i]=tmp[i]; solve(x,y,X,mid,l,p-1); solve(x,mid+1,X,Y,q+1,r); } else { int mid=(X+x)>>1; FOR(i,y,Y) { FOR(j,x,X) FOR(k,y,Y) dis[id(j,k)]=INF; dij(id(mid,i)); FOR(j,l,r) ans[Q[j].id]=min(dis[Q[j].u]+dis[Q[j].v],ans[Q[j].id]); } FOR(i,y,Y) vis[id(mid,i)]=0; int p=l,q=r; FOR(i,l,r) { if(max(Q[i].x,Q[i].X)<=mid) tmp[p++]=Q[i]; if(min(Q[i].x,Q[i].X)>mid) tmp[q--]=Q[i]; } FOR(i,l,r) Q[i]=tmp[i]; solve(x,y,mid,Y,l,p-1); solve(mid+1,y,X,Y,q+1,r); } } int main() { n=read(),m=read(); FOR(i,1,n) FOR(j,1,m-1) { int val=read(); add(id(i,j),id(i,j+1),val); add(id(i,j+1),id(i,j),val); } FOR(i,1,n-1) FOR(j,1,m) { int val=read(); add(id(i,j),id(i+1,j),val); add(id(i+1,j),id(i,j),val); } FOR(i,1,n) FOR(j,1,m) vis[id(i,j)]=1; q=read(); FOR(i,1,q) { Q[i].x=read(),Q[i].y=read(), Q[i].u=id(Q[i].x,Q[i].y); Q[i].X=read(),Q[i].Y=read(), Q[i].v=id(Q[i].X,Q[i].Y); Q[i].id=i,ans[i]=INF; } solve(1,1,n,m,1,q); FOR(i,1,q) printf("%d\n",ans[i]); return 0; }