[BZOJ4456] [Zjoi2016]旅行者 分治+最短路
4456: [Zjoi2016]旅行者
Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 777  Solved: 439
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
2
3
6 4
2
1 1 2 2
1 2 2 1
Sample Output
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]旅行者 分治+最短路的更多相关文章
- 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路
		[BZOJ4456][Zjoi2016]旅行者 Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形 ... 
- 【BZOJ-4456】旅行者     分治 + 最短路
		4456: [Zjoi2016]旅行者 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 254 Solved: 162[Submit][Status] ... 
- BZOJ4456/UOJ#184[Zjoi2016]旅行者 分治 最短路
		原文链接http://www.cnblogs.com/zhouzhendong/p/8682133.html 题目传送门 - BZOJ4456 题目传送门 - UOJ#184 题意 $n\times ... 
- 【BZOJ4456】旅行者(最短路,分治)
		[BZOJ4456]旅行者(最短路,分治) 题面 BZOJ Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北 的道路,这些 ... 
- bzoj4456: [Zjoi2016]旅行者
		题目链接 bzoj4456: [Zjoi2016]旅行者 题解 网格图,对于图分治,每次从中间切垂直于长的那一边, 对于切边上的点做最短路,合并在图两边的答案. 有点卡常 代码 #include< ... 
- [BZOJ4456][ZJOI2016]旅行者:分治+最短路
		分析 类似于点分治的思想,只统计经过分割线的最短路,然后把地图一分为二. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(regist ... 
- BZOJ4456 ZJOI2016旅行者(分治+最短路)
		感觉比较套路,每次在长边中轴线处切一刀,求出切割线上的点对矩形内所有点的单源最短路径,以此更新每个询问,递归处理更小的矩形.因为若起点终点跨过中轴线是肯定要经过的,而不跨过中轴线的则可以选择是否经过中 ... 
- BZOJ.4456.[ZJOI2016]旅行者(分治 Dijkstra)
		题目链接 \(Description\) 给定\(n\times m\)的带边权网格图.\(Q\)次询问从点\((x_i,y_i)\)到点\((x_j,y_j)\)的最短路. \(n\times m\ ... 
- 4456: [Zjoi2016]旅行者
		4456: [Zjoi2016]旅行者 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 分析: 每次对当前矩阵按长边化一条分治线,然后在对分 ... 
随机推荐
- Unity3D开发七惑
			使用Unity3D开发也有大半年了,心中存惑如下,愿与各位开发者一起探讨: (1) 远离普适编程之惑 随着游戏引擎的不断发展,游戏程序员的开发层级也越来越高,以unity3d尤为突出.如果是进行We ... 
- 使用Faster-Rcnn进行目标检测(实践篇)转载
			原 文链接:http://blog.csdn.net/gavin__zhou/article/details/52052915 原理 上一篇文章,已经说过了,大家可以参考一下,Faster-Rcnn进 ... 
- HDU 4417 主席树写法
			Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ... 
- github上面创建文件夹
- File file:/data1/hadoop/yarn/local/usercache/hp/appcache/application_* does not exi
			AM Container for appattempt_1453292851883_0381_000002 exited with exitCode: -1000For more detailed o ... 
- Centos下iptables常用命令
			安装iptablesyum install iptables-services 重启防火墙使配置文件生效systemctl restart iptables.service 设置iptables防火墙 ... 
- 51Nod 1381 硬币游戏 | 概率(数学期望)
			Input 第一行给出一个整数T,表示有T组数据(1<=T<=10000). 第2行到T+1,每行给出一个整数R.(0< R <= 10,000,000,000) Output ... 
- 2015/9/4 Python基础(8):映射和集合类型
			Python里唯一的映射类型是字典.映射类型对象里,hash值(key)和指向的对象(值)是一对多的关系.字典对象是可变的,这一点上很像列表,它也可以存储任意个数任意类型的Python对象,其中包括容 ... 
- 解决SpringSecurity限制iframe引用页面的问题
			使用Spring Security的过程中,需要使用iframe来引入其他域的页面,页面会报X-Frame-Options的错误,试了好几种方法一直未能很好的解决这个问题. 这里涉及到Spring S ... 
- 项目记录 -- python调用回调函数
			C源文件: static int get_callback(zpool_handle_t *zhp, void *data) { zprop_get_cbdata_t *cbp = (zprop_ge ... 
