4456: [Zjoi2016]旅行者

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 777  Solved: 439
[Submit][Status][Discuss]

Description

小Y来到了一个新的城市旅行。她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北
的道路,这些道路两两相交形成n×m个路口 (i,j)(1≤i≤n,1≤j≤m)。她发现不同的道路路况不同,所以通过不
同的路口需要不同的时间。通过调查发现,从路口(i,j)到路口(i,j+1)需要时间 r(i,j),从路口(i,j)到路口(i+1
,j)需要时间c(i,j)。注意这里的道路是双向的。小Y有q个询问,她想知道从路口(x1,y1)到路口(x2,y2)最少需要
花多少时间。

Input

第一行包含 2 个正整数n,m,表示城市的大小。
 
接下来n行,每行包含m?1个整数,第i行第j个正整数表示从一个路口到另一个路口的时间r(i,j)。
 
接下来n?1行,每行包含m个整数,第i行第j个正整数表示从一个路口到另一个路口的时间c(i,j)。
 
接下来一行,包含1个正整数q,表示小Y的询问个数。
 
接下来q行,每行包含4个正整数 x1,y1,x2,y2,表示两个路口的位置。

Output

输出共q行,每行包含一个整数表示从一个路口到另一个路口最少需要花的时间。

Sample Input

2 2
2
3
6 4
2
1 1 2 2
1 2 2 1

Sample Output

6
7

HINT

Source

不想写题解了,发现BZOJ有题解,直接抄就完事了

 实际上分块和分治的思想是差不多的,就直接讲分治吧。。

       首先转离线操作,然后对于某一个矩形区间x∈[lx,rx],y∈[ly,ry],然后要求出所有源点和汇点都在其中的询问,且路径不超出所在区间的答案。不妨设rx-lx>ly-ty,那么对x坐标进行分治,即将这个区间分成两块,那么对于某一个询问,有两种情况:

       1.如果询问的起点和终点在两个不同的块,那么一定会经过中轴线上的一点;

       2.如果在同一块,那么有可能经过中轴线;也有可能路径只在那一块中,就可以递归分治了;

       那么对于某一块,求出中轴线到所在块的所有点的距离,更新一下答案;然后递归分治。

       考虑用dijkstra+heap跑最短路,那么就大概是O(N^1.5logN)的(因为思想和kd-tree是差不多的吧所以时间也一样)。本地测试后两个点dijkstra+heap的时间接近spfa的一半
 #include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#define maxn 20105
using namespace std;
inline int read() {
int x=,f=;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-;
for(;isdigit(ch);ch=getchar()) x=x*+ch-'';
return x*f;
} struct Node {
int x,y,d;
bool operator <(const Node &tmp) const {return d>tmp.d;}
};
struct query {int x1,y1,x2,y2,id;}a[],L[],R[];
int ans[];
int v[maxn][];
int n,m,Q;
int dis[maxn],vis[maxn];
int tx[]={,-,,},ty[]={,,,-};
priority_queue<Node> q;
inline int get(int x,int y) {return (x-)*m+y;}
inline void dij(int x,int y,int x1,int x2,int y1,int y2) {
for(int i=x1;i<=x2;i++) for(int j=y1;j<=y2;j++) dis[get(i,j)]=,vis[get(i,j)]=;
q.push((Node){x,y,});
dis[get(x,y)]=;
while(!q.empty()) {
Node now=q.top();q.pop();
if(vis[get(now.x,now.y)]) continue;
vis[get(now.x,now.y)]=;
for(int i=;i<;i++) {
int tox=now.x+tx[i],toy=now.y+ty[i];
if(tox>x2||tox<x1||toy>y2||toy<y1) continue;
if(dis[get(tox,toy)]>dis[get(now.x,now.y)]+v[get(now.x,now.y)][i]) {
dis[get(tox,toy)]=dis[get(now.x,now.y)]+v[get(now.x,now.y)][i];
q.push((Node){tox,toy,dis[get(tox,toy)]}); }
}
}
}
inline void solve(int x1,int x2,int y1,int y2,int ql,int qr) {
if(qr<ql) return;
if(x1==x2&&y1==y2) {
for(int i=ql;i<=qr;i++) ans[a[i].id]=;
return ;
}
if(x2-x1>y2-y1) {
int mid=(x2+x1)>>;
for(int i=y1;i<=y2;i++) {
dij(mid,i,x1,x2,y1,y2);
for(int j=ql;j<=qr;j++) ans[a[j].id]=min(ans[a[j].id],dis[get(a[j].x1,a[j].y1)]+dis[get(a[j].x2,a[j].y2)]);
}
int l=,r=;
for(int i=ql;i<=qr;i++) {
if(a[i].x1<=mid&&a[i].x2<=mid) L[++l]=a[i];
if(a[i].x1>mid&&a[i].x2>mid) R[++r]=a[i];
}
for(int i=;i<=l;i++) a[ql+i-]=L[i];
for(int i=;i<=r;i++) a[ql+l+i-]=R[i];
solve(x1,mid,y1,y2,ql,ql+l-);solve(mid+,x2,y1,y2,ql+l,ql+l+r-);
}
else {
int mid=(y2+y1)>>;
for(int i=x1;i<=x2;i++) {
dij(i,mid,x1,x2,y1,y2);
for(int j=ql;j<=qr;j++) ans[a[j].id]=min(ans[a[j].id],dis[get(a[j].x1,a[j].y1)]+dis[get(a[j].x2,a[j].y2)]); }
int l=,r=;
for(int i=ql;i<=qr;i++) {
if(a[i].y1<=mid&&a[i].y2<=mid) L[++l]=a[i];
if(a[i].y1>mid&&a[i].y2>mid) R[++r]=a[i];
}
for(int i=;i<=l;i++) a[ql+i-]=L[i];
for(int i=;i<=r;i++) a[ql+l+i-]=R[i];
solve(x1,x2,y1,mid,ql,ql+l-);solve(x1,x2,mid+,y2,ql+l,ql+l+r-);
}
}
int main() {
memset(v,,sizeof(v));
n=read(),m=read();
for(int i=;i<=n;i++) for(int j=;j<m;j++) v[get(i,j)][]=v[get(i,j+)][]=read();
for(int i=;i<n;i++) for(int j=;j<=m;j++) v[get(i,j)][]=v[get(i+,j)][]=read();
Q=read();
for(int i=;i<=Q;i++) {
a[i].x1=read(),a[i].y1=read(),a[i].x2=read(),a[i].y2=read();
a[i].id=i;ans[i]=;
}
solve(,n,,m,,Q);
for(int i=;i<=Q;i++) printf("%d\n",ans[i]);
}

[BZOJ4456] [Zjoi2016]旅行者 分治+最短路的更多相关文章

  1. 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路

    [BZOJ4456][Zjoi2016]旅行者 Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形 ...

  2. 【BZOJ-4456】旅行者 分治 + 最短路

    4456: [Zjoi2016]旅行者 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 254  Solved: 162[Submit][Status] ...

  3. BZOJ4456/UOJ#184[Zjoi2016]旅行者 分治 最短路

    原文链接http://www.cnblogs.com/zhouzhendong/p/8682133.html 题目传送门 - BZOJ4456 题目传送门 - UOJ#184 题意 $n\times ...

  4. 【BZOJ4456】旅行者(最短路,分治)

    [BZOJ4456]旅行者(最短路,分治) 题面 BZOJ Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北 的道路,这些 ...

  5. bzoj4456: [Zjoi2016]旅行者

    题目链接 bzoj4456: [Zjoi2016]旅行者 题解 网格图,对于图分治,每次从中间切垂直于长的那一边, 对于切边上的点做最短路,合并在图两边的答案. 有点卡常 代码 #include< ...

  6. [BZOJ4456][ZJOI2016]旅行者:分治+最短路

    分析 类似于点分治的思想,只统计经过分割线的最短路,然后把地图一分为二. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(regist ...

  7. BZOJ4456 ZJOI2016旅行者(分治+最短路)

    感觉比较套路,每次在长边中轴线处切一刀,求出切割线上的点对矩形内所有点的单源最短路径,以此更新每个询问,递归处理更小的矩形.因为若起点终点跨过中轴线是肯定要经过的,而不跨过中轴线的则可以选择是否经过中 ...

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

    题目链接 \(Description\) 给定\(n\times m\)的带边权网格图.\(Q\)次询问从点\((x_i,y_i)\)到点\((x_j,y_j)\)的最短路. \(n\times m\ ...

  9. 4456: [Zjoi2016]旅行者

    4456: [Zjoi2016]旅行者 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 分析: 每次对当前矩阵按长边化一条分治线,然后在对分 ...

随机推荐

  1. Application Error - The connection to the server was unsuccessful. (file:///android_asset/www/index.html)

    问题描述: PhoneGap+Sencha Touch开发的应用,打包后的APP或者调试期间,在启动的时候提示如下信息: Application Error - The connection to t ...

  2. Codeforces Round #332 (Div. 2)B. Spongebob and Joke

    B. Spongebob and Joke time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  3. Java中equals和==的区别?为什么重写equals方法后,一定要重写hashCode方法?

    首先明确一点,equals是方法,==是操作符. 1. 如果比较的是基本数据类型: 只讨论==,因为equals是不存在的,因为java中基本数据类型不能调用method的. 2. 如果比较的是引用类 ...

  4. 使用 Rational AppScan 保证 Web 应用的安全性,第 2 部分: 使用 Rational AppScan 应对 Web 应用攻击

    1 当前 Web 安全现状 互联网的发展历史也可以说是攻击与防护不断交织发展的过程.目前,全球因特网用户已达 13.5 亿,用户利用网络进行购物.银行转账支付和各种软件下载,企业用户更是依赖于互联网构 ...

  5. gps各种地图坐标系转换

    原文地址:https://my.oschina.net/fankun2013/blog/338100 地图供应商比较多,产生了许多地图坐标.地图坐标正确转换是个问题.在之前开发地图应用的时候发现从WG ...

  6. springboot-用logback将日志文件按等级保存到不同文件

    springboot-用logback将日志文件按等级保存到不同文件 案例: 例如项目基本包名为com.xxx,将该包下的所有日志按debug.info.warn.error等级分别保存到D:/log ...

  7. Windows、Linux及Mac查看端口和杀死进程

    本文介绍如何在Windows.Linux及Mac下查看端口和杀死进程. Windows下查看端口和杀死进程 查看占用端口号的进程号:netstat –ano | findstr "指定端口号 ...

  8. jenkins slave agent 当作服务运行

    1. 接上边编辑好文件 2. 双击以上的jnlp文件 3. 点击弹出的窗口File->save as service, 此时如果报错的话很可能是由于没有安装.net(.net2 以上) 4. 保 ...

  9. Bat 命令相关

    1. bat 里面怎么sleep 等待: ping 127.0.0.1 -n 2000 > nul 2. net use 建立映射: net use Y: \\172.16.10.240\Inf ...

  10. 「6月雅礼集训 2017 Day5」学外语

    [题目大意] 给出$\{P_i\}$,求经过以下操作后能够得到的不同序列个数: 第一步,选择$i, j$,交换$P_i,P_j$:第二步,把所有$P_x=i$的$P_x$变为$j$,把所有$P_x=j ...