[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 分析: 每次对当前矩阵按长边化一条分治线,然后在对分 ...
随机推荐
- SELECT LAST_INSERT_ID() 的使用和注意事项
SELECT LAST_INSERT_ID() 的使用和注意事项 尊重个人劳动成果,转载请注明出处: http://blog.csdn.net/czd3355/article/details/7130 ...
- apache的作用和tomcat的区别
经常在用apache和tomcat等这些服务器,可是总感觉还是不清楚他们之间有什么关系,在用tomcat的时候总出现apache,总感到迷惑,到底谁是主谁是次,因此特意在网上查询了一些这方面的资料,总 ...
- 常见的Java问题
1.什么是java虚拟机?为什么java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件. Java被 ...
- Beagleboneblack的MLO文件干了些啥
Beagleboneblack在启动linux之前还有三个启动阶段: ROM code --> MLO --> u-boot --> kernel 先看看ROM code干了 ...
- elasticsearch 创建索引,以及检索一条数据
elasticsearch的重要概念 我们可以把elasticsearch当做数据库来理解: index:索引库名称,相当于关系型数据库中的表名,一个elasticsearch集群中可以有多个索引库. ...
- Shuffle Cards(牛客第三场+splay)
题目: 题意:将1~n的数进行m次操作,每次操作将第pi位到pi+si-1位的数字移到第一位,求最后的排列. 思路:现在还没不会写splay,在知道这是splay模板题后找了一波别人的模板,虽然过了, ...
- textarea输入框实时统计输入字符数
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- RelativeLayout相对布局中属性值
android:layout_above="@id/xxx" --将控件置于给定ID控件之上 android:layout_below="@id/xxx" ...
- Android控件——AutoCompleteTextView与MultiAutoCompleteTextView(实现自动匹配输入的内容)
------------------------------------AutoCompleteTextView----------------------
- 64_j1
JSCookMenu-2.0.4-13.fc26.noarch.rpm 13-Feb-2017 22:06 38098 Java-WebSocket-1.3.1-0.2.git58d1778.fc24 ...