zoukankan      html  css  js  c++  java
  • [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
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    zyb的面试
    Codeforces Round #514 (Div. 2)
    Maximum GCD(fgets读入)
    Harmonic Number(调和级数+欧拉常数)
    Codeforces Round #516 (Div. 2, by Moscow Team Olympiad)
    Sigma Function (平方数与平方数*2的约数和是奇数)
    Leading and Trailing (数论)
    【贪心】【CF3D】 Least Cost Bracket Sequence
    【套题】qbxt国庆刷题班D1
    【极值问题】【CF1063B】 Labyrinth
  • 原文地址:https://www.cnblogs.com/mleautomaton/p/11167604.html
Copyright © 2011-2022 走看看