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. 003.关于数组的操作 [growing]

    1.获取数组的长度 #include<iostream> using namespace std; template<class T> int length(T& ar ...

  2. phpstorm license 解决

    http://idea.lanyus.com/ sudo vim /etc/hosts 最后添加:  0.0.0.0 account.jetbrains.com 然后把获得的注册码,复制到,licen ...

  3. 通过反射获取T.class代码片段

    说明 持久化框架MyBatis和Hibernate中我们多多少少都会自己取写工具类!但是我们一般都会处理结果集转换成持久化对象,但是我们都要使用类! 代码片段 abstract public clas ...

  4. pythonweb框架

    https://www.cnblogs.com/sss4/p/8097653.html

  5. PHP系统编程--02.PHP守护进程化

    什么是守护进程? 一个守护进程通常补认为是一个不对终端进行控制的后台任务.它有三个很显著的特征:在后台运行,与启动他的进程脱离,无须控制终端.常用的实现方式是fork() -> setsid() ...

  6. word2vec Explained: deriving Mikolov et al.'s negative-sampling word-embedding method

    最近接到任务研究word2vec,感觉网络上关于这个的资料层次不齐,总感觉解释的都没有那么完善.或许就连作者本人也不是非常清楚为什么他的模型好使.论文中提到的negtive sampling给了我很大 ...

  7. jsp 安装环境与基本语法

    1.什么是web应用程序? web应用程序是一种可以通过web访问的应用程序.web应用程序的最大好处是用户很容易访问应用程序.用户只需要有浏览器即可,不需要安装其它软件. 2.搭建 java web ...

  8. 【BZOJ】1574: [Usaco2009 Jan]地震损坏Damage

    [算法]搜索 [题意]给定无向图,现在可能有一些点已经被删除,只给出信息是c个点不能到达结点1,求最少的不能到达结点1的个数(含已删除点). [题解] 真是一道奥妙重重的题目. 每个点不能到达结点1, ...

  9. servlet线程不安全

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlgAAAE9CAIAAABY1Yv/AAAgAElEQVR4nOy9eVxN2/8/viuaU5kqZW

  10. Java的9种基本数据类型的大小,以及他们的封装类

    由于java程序是运行在虚拟机之上的,所以java的基本数据类型的大小是确定的,不会随着操作系统的位数的改变而改变. 在计算机中,存储的是0,1,0,1这样的二进制位,表示为bit,1Byte = 8 ...