[ZJOI2016]旅行者

考虑看到网格图求最短路,直接分治,然后往长的那边分就行了。

复杂度分析:

显然每一次都会有\(x\)\(y\)的减半,那么这样子复杂度就应该是\(\Theta(nlog(n) \sqrt{n})\)

洛谷不开\(O2\)还过不去\(QwQ\)

// luogu-judger-enable-o2
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define re register
#define ll long long
inline int gi(){
	int f=1,sum=0;char ch=getchar();
	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return f*sum;
}
const int N=100010,Inf=1e9+10;
int n,m,front[N],dis[N],cnt,X[N],Y[N],vis[N],ans[N];
int id(int x,int y){return (x-1)*m+y;}
struct node{int to,nxt,w;}e[N<<1];
struct ques{int s,t,id;}q[N],lq[N],rq[N];
void Add(int u,int v,int w){e[++cnt]=(node){v,front[u],w};front[u]=cnt;e[++cnt]=(node){u,front[v],w};front[v]=cnt;}
typedef pair<int,int> pii;
#define mp make_pair
void dijkstra(int s,int lx,int rx,int ly,int ry){
	for(int i=lx;i<=rx;i++)
		for(int j=ly;j<=ry;j++)
			dis[id(i,j)]=Inf;
	static priority_queue<pii,vector<pii>,greater<pii> >que;
	dis[s]=0;que.push(mp(0,s));
	while(!que.empty()){
		pii now=que.top();que.pop();int u=now.second;
		if(dis[u]<now.first)continue;
		for(int i=front[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(X[v]<lx || X[v]>rx || Y[v]<ly || Y[v]>ry)continue;
			if(dis[u]+e[i].w<dis[v]){
				dis[v]=dis[u]+e[i].w;que.push(mp(dis[v],v));
			}
		}
	}
}
void div(int st,int ed,int lx,int rx,int ly,int ry){
	if(st>ed)return;
	if(rx-lx>=ry-ly){
		int mid=(lx+rx)>>1;
		for(int i=ly;i<=ry;i++){
			dijkstra(id(mid,i),lx,rx,ly,ry);
			for(int j=st;j<=ed;j++)ans[q[j].id]=min(ans[q[j].id],dis[q[j].s]+dis[q[j].t]);
		}
		int lt=0,rt=0;
		for(int i=st;i<=ed;i++){
			if(X[q[i].s]<mid && X[q[i].t]<mid)lq[++lt]=q[i];
			if(X[q[i].s]>mid && X[q[i].t]>mid)rq[++rt]=q[i];
		}
		for(int i=1;i<=lt;i++)q[st+i-1]=lq[i];
		for(int i=1;i<=rt;i++)q[st+i+lt-1]=rq[i];
		div(st,st+lt-1,lx,mid-1,ly,ry);
		div(st+lt,st+lt+rt-1,mid+1,rx,ly,ry);
	}
	else{
		int mid=(ly+ry)>>1;
		for(int i=lx;i<=rx;i++){
			dijkstra(id(i,mid),lx,rx,ly,ry);
			for(int j=st;j<=ed;j++)ans[q[j].id]=min(ans[q[j].id],dis[q[j].s]+dis[q[j].t]);
		}
		int lt=0,rt=0;
		for(int i=st;i<=ed;i++){
			if(Y[q[i].s]<mid && Y[q[i].t]<mid)lq[++lt]=q[i];
			if(Y[q[i].s]>mid && Y[q[i].t]>mid)rq[++rt]=q[i];
		}
		for(int i=1;i<=lt;i++)q[st+i-1]=lq[i];
		for(int i=1;i<=rt;i++)q[st+i+lt-1]=rq[i];
		div(st,st+lt-1,lx,rx,ly,mid-1);
		div(st+lt,st+lt+rt-1,lx,rx,mid+1,ry);
	}
}
int main(){
	n=gi();m=gi();
	for(int i=1;i<=n;i++)
		for(int j=1;j<m;j++)
			Add(id(i,j),id(i,j+1),gi());
	for(int i=1;i<n;i++)
		for(int j=1;j<=m;j++)
			Add(id(i,j),id(i+1,j),gi());
	int Q=gi();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			X[id(i,j)]=i,Y[id(i,j)]=j;
	for(int i=1;i<=Q;i++){
		int x1=gi(),y1=gi(),x2=gi(),y2=gi();
		q[i]=(ques){id(x1,y1),id(x2,y2),i};ans[i]=Inf;
	}
	div(1,Q,1,n,1,m);
	for(int i=1;i<=Q;i++)printf("%d\n",ans[i]);
	return 0;
}
posted @ 2019-07-11 02:22  QwQGJH  阅读(199)  评论(0编辑  收藏  举报