分治+Dij
也没想象中的难写,就是有轻微卡常
#pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #include<cstdio> #include<queue> #include<algorithm> #include<iostream> #include<ext/pb_ds/priority_queue.hpp> const int maxn = 20100; using std::max; using std::min; int n,m; int dis[maxn],vis[maxn]; struct P{ int x,y,dis; __attribute__((always_inline)) operator int()const{return (x-1)*m+y;} __attribute__((always_inline)) int operator <(const P&b)const{return dis>b.dis;} }; struct Q{P a,b;int ans;}b[100100]; inline void down(int&x,int y){if(x>y)x=y;} struct T{ P to; int nxt,v; }way[maxn<<2]; int h[maxn],num; inline void adde(P x,P y,int v){ way[++num]={y,h[x],v},h[x]=num; way[++num]={x,h[y],v},h[y]=num; } __gnu_pbds::priority_queue<P>q; __gnu_pbds::priority_queue<P>::point_iterator iter[maxn]; inline void run(int x,int y,int x1,int y1,int x2,int y2){ for(int i=x1;i<=x2;++i) for(int j=y1;j<=y2;++j) dis[(i-1)*m+j]=1e9,iter[(i-1)*m+j]=q.push({i,j,(int)1e9}); dis[(x-1)*m+y]=0,q.modify(iter[(x-1)*m+y],{x,y,0}); while(!q.empty()){ P t=q.top();q.pop();int Ds = dis[t]; for(int i=h[t];i;i=way[i].nxt){ P z = way[i].to;int Z=z; if(x1 <= z.x && z.x <= x2 && y1 <= z.y && z.y <= y2 && dis[Z]>Ds+way[i].v){ z.dis=dis[Z]=Ds+way[i].v; q.modify(iter[Z],z); } } } } inline void solve(int x1,int y1,int x2,int y2,std::vector<Q*>&v){ if(x1 > x2 || y1 > y2 || v.empty())return ; if(x1 == x2 && y1 == y2){ for(Q*&i:v)i->ans=0; return ; } if(x2-x1 >= y2-y1){ int mid = x1 + x2 >> 1; for(int i=y1;i<=y2;++i){ run(mid,i,x1,y1,x2,y2); for(Q*&i:v)down(i->ans,dis[i->a]+dis[i->b]); } std::vector<Q*> v1,v2; for(Q*i:v){ if(max(i->a.x,i->b.x) < mid)v1.emplace_back(i); if(min(i->a.x,i->b.x) > mid)v2.emplace_back(i); } solve(x1,y1,mid-1,y2,v1),solve(mid+1,y1,x2,y2,v2); }else{ int mid=y1 + y2 >> 1; for(int i=x1;i<=x2;++i){ run(i,mid,x1,y1,x2,y2); for(Q*i:v)down(i->ans,dis[i->a]+dis[i->b]); } std::vector<Q*> v1,v2; for(Q*&i:v){ if(max(i->a.y,i->b.y) < mid)v1.emplace_back(i); if(min(i->a.y,i->b.y) > mid)v2.emplace_back(i); } solve(x1,y1,x2,mid-1,v1),solve(x1,mid+1,x2,y2,v2); } } char buf[(int)3e7],*vin=buf-1; char bufo[(int)3e7],*vout=bufo-1; inline void pc(int x){*++vout=x;} inline void put(int x){if(x>9)put(x/10);pc(x%10+48);} #define getchar() (*++vin) int x,ch; inline int read(){ while(isspace(ch=getchar()));x=ch&15; while(isdigit(ch=getchar()))x=x*10+(ch&15); return x; } int main(){ fread(buf,1,sizeof buf,stdin); n=read(),m=read(); for(int i=1;i<=n;++i) for(int j=1;j<m;++j){ adde({i,j},{i,j+1},read()); } for(int i=1;i<n;++i) for(int j=1;j<=m;++j){ adde({i,j},{i+1,j},read()); } int q=read();; std::vector<Q*> v; for(int i=1;i<=q;++i) b[i].a.x=read(),b[i].a.y=read(),b[i].b.x=read(),b[i].b.y=read(),b[i].ans=2e9,v.push_back(b+i); solve(1,1,n,m,v); for(int i=1;i<=q;++i) put(b[i].ans),pc(10); fwrite(bufo,1,vout-bufo+1,stdout); }