4456: [Zjoi2016]旅行者

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 254  Solved: 162
[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

Solution

分治每次求起点和终点都在[xl,xr],[yl,yr]的答案。

考虑对这个大矩形进行分割。

把比较短的一维切成两半,并枚举切割的这条中线上的所有点,并从这些点向其余各点求最短路。然后用最短路得到的答案去更新答案。然后递归分治;

分析一下复杂度:$logN$的分治,因为每次切较短边,所以复杂度最多不超过$\sqrt{N}$,最后还有Dijskra的$NlogN$

个人感觉大概是$O(N\sqrt{N}log^{2}N)$的复杂度,但是,网上有严格的证明复杂度,是$O(N\sqrt{N}logN)$的,并不是很会,戳这里吧

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
inline int read()
{
int x=; char ch=getchar();
while (ch<'' || ch>'') {ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x;
}
#define MAXN 20010
int N,M,Q,tp;
vector<int>id[MAXN];
struct EdgeNode{int next,to,d;}edge[MAXN<<];
int head[MAXN],cnt=;
inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].d=w;}
inline void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
#define Pa pair<int,int>
#define INF 0x7fffffff
priority_queue<Pa,vector<Pa>,greater<Pa> >q;
int dis[MAXN],X[MAXN],Y[MAXN];
bool visit[MAXN];
inline void Dijkstra(int S,int xl,int xr,int yl,int yr)
{
for (int i=xl; i<=xr; i++)
for (int j=yl; j<=yr; j++)
dis[id[i][j]]=INF;
q.push(make_pair(,S)); dis[S]=;
while (!q.empty())
{
int now=q.top().second;
int Dis=q.top().first;
q.pop();
if (Dis>dis[now]) continue;
for (int i=head[now]; i; i=edge[i].next)
if (X[edge[i].to]<xl || X[edge[i].to]>xr || Y[edge[i].to]<yl || Y[edge[i].to]>yr) continue;
else
if (Dis + edge[i].d < dis[edge[i].to])
dis[edge[i].to]=Dis+edge[i].d,
q.push(make_pair(dis[edge[i].to],edge[i].to));
}
// puts("DIS");
// for (int i=xl; i<=xr; i++)
// for (int j=yl; j<=yr; j++)
// printf("%d ",dis[id[i][j]]);
// puts("");
}
#define MAXQ 100010
int ans[MAXQ];
struct AskNode{int x0,y0,x1,y1,id,u,v;}ask[MAXQ],tmp[MAXQ];
void CDQ(int xl,int xr,int yl,int yr,int ql,int qr)
{
if (ql>qr) return;
bool f=; int l,r;
if (xr-xl<yr-yl) l=yl,r=yr,f=; else l=xl,r=xr,f=;
int mid=(l+r)>>;
// printf("CDQ(%d,%d,%d,%d,%d,%d,%d)\n",xl,xr,yl,yr,ql,qr,mid);
if (f)
for (int i=xl; i<=xr; i++)
{
Dijkstra(id[i][mid],xl,xr,yl,yr);
for (int j=ql; j<=qr; j++)
ans[ask[j].id]=min(ans[ask[j].id],dis[ask[j].u]+dis[ask[j].v]);
}
else
for (int i=yl; i<=yr; i++)
{
Dijkstra(id[mid][i],xl,xr,yl,yr);
for (int j=ql; j<=qr; j++)
ans[ask[j].id]=min(ans[ask[j].id],dis[ask[j].u]+dis[ask[j].v]);
}
int L=ql-,R=qr+;
for (int i=ql; i<=qr; i++)
if (f)
if (ask[i].y0<mid && ask[i].y1<mid) tmp[++L]=ask[i]; else if (ask[i].y0>mid && ask[i].y1>mid) tmp[--R]=ask[i]; else;
else
if (ask[i].x0<mid && ask[i].x1<mid) tmp[++L]=ask[i]; else if (ask[i].x0>mid && ask[i].x1>mid) tmp[--R]=ask[i]; else;
for (int i=ql; i<=L; i++) ask[i]=tmp[i];
for (int i=R; i<=qr; i++) ask[i]=tmp[i];
if (f) CDQ(xl,xr,yl,mid-,ql,L),CDQ(xl,xr,mid+,yr,R,qr);
else CDQ(xl,mid-,yl,yr,ql,L),CDQ(mid+,xr,yl,yr,R,qr);
}
int main()
{
N=read(),M=read();
for (int i=; i<=N; i++) id[i].push_back();
for (int i=,ID=; i<=N; i++)
for (int j=; j<=M; j++)
id[i].push_back(++ID),X[ID]=i,Y[ID]=j;
for (int i=,len; i<=N; i++)
for (int j=; j<=M-; j++)
len=read(),InsertEdge(id[i][j],id[i][j+],len);
for (int i=,len; i<=N-; i++)
for (int j=; j<=M; j++)
len=read(),InsertEdge(id[i][j],id[i+][j],len);
Q=read();
while (Q--)
{
tp++; ask[tp].id=tp;
ask[tp].x0=read(); ask[tp].y0=read(); ask[tp].u=id[ask[tp].x0][ask[tp].y0];
ask[tp].x1=read(); ask[tp].y1=read(); ask[tp].v=id[ask[tp].x1][ask[tp].y1];
if (ask[tp].u==ask[tp].v) ans[tp]=; else ans[tp]=INF;
}
CDQ(,N,,M,,tp);
for (int i=; i<=tp; i++) printf("%d\n",ans[i]);
return ;
}

UOJ只能跑过50分,BZOJ 17sAC....

比别人慢很多,于是试了试spfa,然后...UOJ40,BZOJ TLE

BZOJ  Dijsktra与spfa的对比:

【BZOJ-4456】旅行者 分治 + 最短路的更多相关文章

  1. [BZOJ4456] [Zjoi2016]旅行者 分治+最短路

    4456: [Zjoi2016]旅行者 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 777  Solved: 439[Submit][Status] ...

  2. 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路

    [BZOJ4456][Zjoi2016]旅行者 Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形 ...

  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. bzoj 4456 [Zjoi2016]旅行者

    题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 题解 分治 设当前work的区间为(x1,y1,x2,y2) 我们将长边分成两半 不妨 ...

  6. 【BZOJ5506】[GXOI/GZOI2019]旅行者(最短路)

    [BZOJ5506][GXOI/GZOI2019]旅行者(最短路) 题面 BZOJ 洛谷 题解 正着做一遍\(dij\)求出最短路径以及从谁转移过来的,反过来做一遍,如果两个点不由同一个点转移过来就更 ...

  7. BZOJ.4456.[ZJOI2016]旅行者(分治 Dijkstra)

    题目链接 \(Description\) 给定\(n\times m\)的带边权网格图.\(Q\)次询问从点\((x_i,y_i)\)到点\((x_j,y_j)\)的最短路. \(n\times m\ ...

  8. 【BZOJ 4456】【UOJ #184】【ZJOI 2016】旅行者

    http://www.lydsy.com/JudgeOnline/problem.php?id=4456 http://uoj.ac/problem/184 参考(抄)的晨爷的题解(代码) 对矩形进行 ...

  9. 2090. 「ZJOI2016」旅行者 分治,最短路

    2090. 「ZJOI2016」旅行者 链接 loj 思路 \((l,mid)(mid+1,r)\).考虑跨过mid的贡献. 假设选的中间那条线的点为gzy,贡献为\(dis(x,gzy)+dis(g ...

随机推荐

  1. Javascript的ArrayBuffer从Utf8ArrayToString

    由于项目需要,需要从一个已知的ArrayBuffer中读取出字符串,虽然环境是typescript,但最终还是用的js的代码改了一下解决, public Utf8ArrayToStr(array):s ...

  2. filestream read方法 循环读取固定文件

    1.循环读取啊,byte[]可以定义为1024或者2049等等,不要超过int的maxvalue就可以.然后取出来操作完再去取. FileStream stream = new FileStream( ...

  3. C#计算文件的MD5值实例

    C#计算文件的MD5值实例 MD5 是 Message Digest Algorithm 5(信息摘要算法)的缩写,MD5 一种散列(Hash)技术,广泛用于加密.解密.数据签名和数据完整性校验等方面 ...

  4. mvc route的注册,激活,调用流程

    mvc route的注册,激活,调用流程(三) net core mvc route的注册,激活,调用流程 mvc的入口是route,当前请求的url匹配到合适的route之后,mvc根据route所 ...

  5. jquery选择器空格与大于号、加号与波浪号的区别

    空格:$('parent childchild')表示获取parent下的所有的childchild节点,所有的子孙. 大于号:$('parent > child')表示获取parent下的所有 ...

  6. 数据库mark

    LOAD DATA INFILE 'I:\QQpwd\\1.txt' IGNORE INTO TABLE sgk.top1 FIELDS TERMINATED BY '----' OPTIONALLY ...

  7. FineUI小技巧(2)将表单内全部字段禁用、只读、设置无效标识

    需求描述 对表单内的所有字段进行操作也是常见需求,这些操作有: 禁用:表单字段变灰,不响应用户动作. 只读:表单字段不变灰,但不接受用户输入(实际上是设置DOM节点的readonly属性),有触发器的 ...

  8. 一次由于开启 Safari 无痕浏览 引发的艰难“捉虫”事件

    事件回顾 做了一个移动端的页面,测试的时候出现了一个诡异的 bug.别的浏览器都好好的,就 ios 的 Safari 浏览器页面停止了渲染,似乎是有一段 js 文件没有载入.但是奇怪的是,同一型号的 ...

  9. 初学git:用git bash往github push代码

    对于我来说,最开始使用github主要是为了使用它的pages功能展示demo.其实这些都是用Github for Windows push上去的,图形化界面的客户端使用确实简单,但是逼格不够,好吧其 ...

  10. Java 的世界,我不懂:奇葩的 json 序列化

    先上张图,代表我心中的十万头草泥马: 写这么长的代码,头回见数组和单个实体共用同一个 json 节点的! 恐怕只有 java 社区的大牛B 才能做出这等事.. 由 Apache 发布: http:// ...