• BZOJ.4456.[ZJOI2016]旅行者(分治 Dijkstra)


    题目链接

    (Description)

      给定(n imes m)的带边权网格图。(Q)次询问从点((x_i,y_i))到点((x_j,y_j))的最短路。
      (n imes mleq 2 imes 10^4,Qleq 10^5).

    (Solution)

      对分治线上的每个点进行一次Dijkstra。若该区域点数(面积)为S,则分治线如果选择较短的一边,其上点的个数(leqsqrt S)。每次选较短的分治复杂度(O(Ssqrt Slog S)),若不这样复杂度(O(Ssqrt Slog^2 S))。((T(n)=T(frac{n}{2})+O(Ssqrt Slog S)=O(Ssqrt Slog S))?网上题解有证明。)
      若一次询问的((x,y))在分治线两侧,则可以枚举分治线上的点(i)(min{dis_{i,x}+dis_{i,y}})更新答案,然后删掉这个询问;若((x,y))在分治线同侧,则也用(min{dis_{i,x}+dis_{i,y}})更新一次过分治线的答案,继续分治。

    //5804kb	18088ms
    //怎么这么慢啊。。赋值也比调用快么。。
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    //#define gc() getchar()
    #define MAXIN 400000
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    #define ID(x,y) ((x-1)*m+y)
    #define mp std::make_pair
    #define pr std::pair<int,int>
    const int N=2e4+5,M=1e5+5,Way[5]={0,-1,0,1,0};
    
    int n,m,val[N][4],dis[N],Ans[M],seq[M],tmp[M],X[N],Y[N];//0:left 1:up 2:right 3:down
    char IN[MAXIN],*SS=IN,*TT=IN;
    struct Queries
    {
    	int xa,xb,ya,yb,x,y,id;
    }q[M];
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    void Dijkstra(int s,int xa,int ya,int xb,int yb)
    {
    	static int Time,vis[N],upd[N];
    	static std::priority_queue<pr> q;
    
    	upd[s]=++Time, q.push(mp(dis[s]=0,s));
    	while(!q.empty())
    	{
    		int now=q.top().second;
    		q.pop();
    		if(vis[now]==Time) continue;
    		vis[now]=Time;
    //		int x=(now-1)/m+1, y=now%m; if(!y) y=m;
    		int x=X[now], y=Y[now];
    		for(int v,xn,yn,i=0; i<4; ++i)
    		{
    			if((xn=x+Way[i])<xa||xn>xb||(yn=y+Way[i+1])<ya||yn>yb) continue;
    			if((upd[v=ID(xn,yn)]!=Time&&(upd[v]=Time))/*初始值INF*/||dis[v]>dis[now]+val[now][i])
    				q.push(mp(-(dis[v]=dis[now]+val[now][i]),v));
    		}
    	}
    }
    void Solve(int xa,int ya,int xb,int yb,int l,int r)
    {
    	if(xa>xb||ya>yb||l>r) return;
    	if(xb-xa<=yb-ya)
    	{
    		int mid=ya+yb>>1;
    		for(int i=xa; i<=xb; ++i)
    		{
    			Dijkstra(ID(i,mid),xa,ya,xb,yb);
    			for(int id,j=l; j<=r; ++j)
    				id=seq[j], Ans[q[id].id]=std::min(Ans[q[id].id],dis[q[id].x]+dis[q[id].y]);
    		}
    		int nowl=l, nowr=r;
    		for(int id,i=l; i<=r; ++i)
    			if(q[id=seq[i]].ya<mid && q[id].yb<mid) tmp[nowl++]=id;
    			else if(q[id].ya>mid && q[id].yb>mid) tmp[nowr--]=id;
    		for(int i=l; i<nowl; ++i) seq[i]=tmp[i];
    		for(int i=nowr+1; i<=r; ++i) seq[i]=tmp[i];
    		Solve(xa,ya,xb,mid-1,l,nowl-1), Solve(xa,mid+1,xb,yb,nowr+1,r);
    	}
    	else
    	{
    		int mid=xa+xb>>1;
    		for(int i=ya; i<=yb; ++i)
    		{
    			Dijkstra(ID(mid,i),xa,ya,xb,yb);
    			for(int id,j=l; j<=r; ++j)
    				id=seq[j], Ans[q[id].id]=std::min(Ans[q[id].id],dis[q[id].x]+dis[q[id].y]);
    		}
    		int nowl=l, nowr=r;
    		for(int id,i=l; i<=r; ++i)
    			if(q[id=seq[i]].xa<mid && q[id].xb<mid) tmp[nowl++]=id;
    			else if(q[id].xa>mid && q[id].xb>mid) tmp[nowr--]=id;
    		for(int i=l; i<nowl; ++i) seq[i]=tmp[i];
    		for(int i=nowr+1; i<=r; ++i) seq[i]=tmp[i];
    		Solve(xa,ya,mid-1,yb,l,nowl-1), Solve(mid+1,ya,xb,yb,nowr+1,r);
    	}
    }
    
    int main()
    {
    	n=read(), m=read();
    	for(int i=1,tot=1; i<=n; ++i,++tot)
    		for(int j=1; j<m; ++j,++tot) val[tot][2]=val[tot+1][0]=read();
    	for(int i=1,tot=1; i<n; ++i)
    		for(int j=1; j<=m; ++j,++tot) val[tot][3]=val[tot+m][1]=read();
    	for(int i=1,tot=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j,++tot) X[tot]=i, Y[tot]=j;
    	memset(Ans,0x3f,sizeof Ans);
    	int Q=read();
    	for(int i=1,xa,ya,xb,yb; i<=Q; ++i)
    	{
    		xa=read(), ya=read(), xb=read(), yb=read();
    //		if(xa==xb && ya==yb) Ans[i]=0;
    		seq[i]=i, q[i]=(Queries){xa,xb,ya,yb,ID(xa,ya),ID(xb,yb),i};
    	}
    	Solve(1,1,n,m,1,Q);
    	for(int i=1; i<=Q; ++i) printf("%d
    ",Ans[i]);
    
    	return 0;
    }
    
  • 相关阅读:
    mysql的一些不常用语句
    redis的使用1
    linux理论知识点(用于考试)
    服务器负载均衡数据同步的实现
    解决com.ibatis.sqlmap.client.SqlMapException: There is no statement named in this SqlMap
    cvc-complex-type.2.3: Element 'beans' cannot have character [children]
    Oracle11g服务详细介绍及哪些服务是必须开启的
    Oracle
    oracle 帐号scott被锁定 如何解锁
    记录
  • 原文地址:https://www.cnblogs.com/SovietPower/p/9415832.html
Copyright © 2020-2023  润新知