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. SELECT LAST_INSERT_ID() 的使用和注意事项

    SELECT LAST_INSERT_ID() 的使用和注意事项 尊重个人劳动成果,转载请注明出处: http://blog.csdn.net/czd3355/article/details/7130 ...

  2. apache的作用和tomcat的区别

    经常在用apache和tomcat等这些服务器,可是总感觉还是不清楚他们之间有什么关系,在用tomcat的时候总出现apache,总感到迷惑,到底谁是主谁是次,因此特意在网上查询了一些这方面的资料,总 ...

  3. 常见的Java问题

    1.什么是java虚拟机?为什么java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件. Java被 ...

  4. Beagleboneblack的MLO文件干了些啥

    Beagleboneblack在启动linux之前还有三个启动阶段: ROM code  -->  MLO  -->  u-boot --> kernel 先看看ROM code干了 ...

  5. elasticsearch 创建索引,以及检索一条数据

    elasticsearch的重要概念 我们可以把elasticsearch当做数据库来理解: index:索引库名称,相当于关系型数据库中的表名,一个elasticsearch集群中可以有多个索引库. ...

  6. Shuffle Cards(牛客第三场+splay)

    题目: 题意:将1~n的数进行m次操作,每次操作将第pi位到pi+si-1位的数字移到第一位,求最后的排列. 思路:现在还没不会写splay,在知道这是splay模板题后找了一波别人的模板,虽然过了, ...

  7. textarea输入框实时统计输入字符数

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. RelativeLayout相对布局中属性值

    android:layout_above="@id/xxx"  --将控件置于给定ID控件之上 android:layout_below="@id/xxx"  ...

  9. Android控件——AutoCompleteTextView与MultiAutoCompleteTextView(实现自动匹配输入的内容)

    ------------------------------------AutoCompleteTextView----------------------

  10. 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 ...