[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 分析: 每次对当前矩阵按长边化一条分治线,然后在对分 ...
随机推荐
- springboot的application.properties与.yml的区别
现在我们的application.properties文件内容是: server.port=8090 server.session-timeout=30 server.context-path= se ...
- 深入探析 Rational AppScan Standard Edition 多步骤操作
序言 IBM Rational AppScan Standard(下文简称 AppScan)作为面向 Web 应用安全黑盒检测的自动化工具,得到业界的广泛认可和应用.很多人使用 AppScan 时都采 ...
- Anaconda创建python(2.7/3.6)的虚拟环境后需要添加ipykernel
今天在工作的过程中遇到这样一个问题:安装完Anaconda利用conda创建了虚拟环境,但是启动jupyter notebook之后却找不到虚拟环境中的python kernel.后来上网找到了解决办 ...
- HashMap详谈以及实现原理
(一).HashMap 基于哈希表的 Map 接口的实现 允许使用 null 值和 null 键 HashMap不是线程安全,想要线程安全,Collections类的静态方法synchronizedM ...
- 【51NOD-0】1058 N的阶乘的长度
[算法]数学 [题解]n!的位数相当于ans=log10(n!)上取整,然后就可以拆出来加了. 可以用log10(i)或log(i)/log(10) 阶乘好像有个斯特林公式…… #include< ...
- 如何设计一个优雅健壮的Android WebView?(下)
转:如何设计一个优雅健壮的Android WebView?(下) 前言 在上文<如何设计一个优雅健壮的Android WebView?(上)>中,笔者分析了国内WebView的现状,以及在 ...
- css纯样式导航
<style>.dropdown { position: relative; display: inline-block;} .dropdown-content { di ...
- perl6 修改文件并覆盖
use v6; my $filename = 'data.txt'; my $data = slurp $filename; say $data; $data ~~ s/'4'/'ABC'/; say ...
- Java21个基础知识点
类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: (1) 装载:查找和导入Class文件: (2) 链接:把类的二进制 ...
- ThinkPHP5 正则验证中有“|”时提示“规则错误”的解决方案
正则规则中有“|”时,会引起解析错误: 'regex:\d{3,4}[\s,-]?\d{7,8}|1[3,4,5,8]\d[\s,-]?\d{4}[\s,-]?\d{4}' 使用数组语法可以解决: [ ...