BZOJ4456 ZJOI2016旅行者(分治+最短路)
感觉比较套路,每次在长边中轴线处切一刀,求出切割线上的点对矩形内所有点的单源最短路径,以此更新每个询问,递归处理更小的矩形。因为若起点终点跨过中轴线是肯定要经过的,而不跨过中轴线的则可以选择是否经过中轴线,若不经过一定就在矩形的某一半了。复杂度O((nm)1.5log(nm)),不太会证。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 20010
#define M 200
#define Q 100010
int n,m,u,op,a[N*M][],dis[M][N],ans[Q];
struct data{int sx,sy,tx,ty,i;
}q[Q],tmp[Q];
int wx[]={-,,,},wy[]={,,,-};
int trans(int x,int y){return (x-)*m+y;}
namespace shortestpath
{
int p[N],t;bool flag[N];
struct data{int to,nxt,len;}edge[N<<];
struct data2
{
int x,d;
bool operator <(const data2&a) const
{
return d>a.d;
}
};
priority_queue<data2> q;
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
void dijkstra(int x,int y,int k)
{
while (!q.empty()) q.pop();
memset(dis[k],,sizeof(dis[k]));dis[k][trans(x,y)]=;q.push((data2){trans(x,y),});
memset(flag,,sizeof(flag));
while ()
{
while (!q.empty()&&flag[q.top().x]) q.pop();
if (q.empty()) break;
data2 v=q.top();q.pop();
flag[v.x]=;
for (int j=p[v.x];j;j=edge[j].nxt)
if (v.d+edge[j].len<dis[k][edge[j].to])
{
dis[k][edge[j].to]=v.d+edge[j].len;
q.push((data2){edge[j].to,dis[k][edge[j].to]});
}
}
}
void make(int u,int d,int l,int r)
{
t=;
for (int i=u;i<=d;i++)
for (int j=l;j<=r;j++)
p[trans(i,j)]=;
for (int i=u;i<=d;i++)
for (int j=l;j<=r;j++)
for (int k=;k<;k++)
if (i+wx[k]>=u&&i+wx[k]<=d&&j+wy[k]>=l&&j+wy[k]<=r)
addedge(trans(i,j),trans(i+wx[k],j+wy[k]),a[trans(i,j)][k]);
}
}
void solve(int u,int d,int l,int r,int x,int y)
{
if (u>d||l>r||x>y) return;
shortestpath::make(u,d,l,r);
if (d-u<=r-l)
{
int mid=l+r>>,s=x-,t=y+;
for (int i=u;i<=d;i++) shortestpath::dijkstra(i,mid,i-u+);
for (int i=x;i<=y;i++)
{
for (int j=;j<=d-u+;j++)
ans[q[i].i]=min(ans[q[i].i],dis[j][trans(q[i].sx,q[i].sy)]+dis[j][trans(q[i].tx,q[i].ty)]);
if (max(q[i].sy,q[i].ty)<mid) tmp[++s]=q[i];
else if (min(q[i].sy,q[i].ty)>mid) tmp[--t]=q[i];
}
for (int i=x;i<=s;i++) q[i]=tmp[i];
for (int i=t;i<=y;i++) q[i]=tmp[i];
solve(u,d,l,mid-,x,s),
solve(u,d,mid+,r,t,y);
}
else
{
int mid=u+d>>,s=x-,t=y+;
for (int i=l;i<=r;i++) shortestpath::dijkstra(mid,i,i-l+);
for (int i=x;i<=y;i++)
{
for (int j=;j<=r-l+;j++)
ans[q[i].i]=min(ans[q[i].i],dis[j][trans(q[i].sx,q[i].sy)]+dis[j][trans(q[i].tx,q[i].ty)]);
if (max(q[i].sx,q[i].tx)<mid) tmp[++s]=q[i];
else if (min(q[i].sx,q[i].tx)>mid) tmp[--t]=q[i];
}
for (int i=x;i<=s;i++) q[i]=tmp[i];
for (int i=t;i<=y;i++) q[i]=tmp[i];
solve(u,mid-,l,r,x,s),
solve(mid+,d,l,r,t,y);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4456.in","r",stdin);
freopen("bzoj4456.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
for (int i=;i<=n;i++)
for (int j=;j<m;j++)
a[trans(i,j)][]=a[trans(i,j+)][]=read();
for (int i=;i<n;i++)
for (int j=;j<=m;j++)
a[trans(i,j)][]=a[trans(i+,j)][]=read();
u=read();
for (int i=;i<=u;i++)
q[i].sx=read(),q[i].sy=read(),q[i].tx=read(),q[i].ty=read(),q[i].i=i;
memset(ans,,sizeof(ans));
solve(,n,,m,,u);
for (int i=;i<=u;i++) printf("%d\n",ans[i]);
return ;
}
BZOJ4456 ZJOI2016旅行者(分治+最短路)的更多相关文章
- [BZOJ4456] [Zjoi2016]旅行者 分治+最短路
4456: [Zjoi2016]旅行者 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 777 Solved: 439[Submit][Status] ...
- 【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 ...
- 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 分析: 每次对当前矩阵按长边化一条分治线,然后在对分 ...
随机推荐
- Linux运维一定要知道的六类好习惯和23个教训,避免入坑!
Linux运维一定要知道的六类好习惯和23个教训,避免入坑! 从事运维三年半,遇到过各式各样的问题,数据丢失,网站挂马,误删数据库文件,黑客攻击等各类问题. 今天简单整理一下,分享给各位小伙伴. 一. ...
- linux下的shadow文件解释
/etc/shadow //用户密码文件登录名:加密口令:最后一次修改时间:最小时间间隔:最大时间间隔:警告时间:不活动时间:失效时间:标志 root:$1$202cb962ac59075b964b0 ...
- phpstorm代码提示不小心关了,如何开启
在phpstrom右下角单击如图 出现event log窗口 如果不是 单击切换取消节电模式即可开启代码提示.
- spring-boot整合ehcache实现缓存机制
EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. ehcache提供了多种缓存策略,主要分为内存和磁盘两级,所以无需担心 ...
- 关于mysql连接时候出现"error 2003: can't connect to mysql server on 'localhost'(10061)问题的解决
天,在使用navicat Premium 连接数据库时,出现了一个弹出窗口显示: "error 2003: can't connect to mysql server on 'localho ...
- (杭电 1097)A hard puzzle
A hard puzzle Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- (数据科学学习手札09)系统聚类算法Python与R的比较
上一篇笔者以自己编写代码的方式实现了重心法下的系统聚类(又称层次聚类)算法,通过与Scipy和R中各自自带的系统聚类方法进行比较,显然这些权威的快捷方法更为高效,那么本篇就系统地介绍一下Python与 ...
- 牛客暑假多校第五场A.gpa
一.题意 给出你的N门课程的考试成绩和所占的机电数目.允许你放弃K门课的成绩,要求你的平均学分绩最高能达到多少. Kanade selected n courses in the university ...
- python2.7练习小例子(十八)
19):题目:一个数如果恰好等于它的因子之和,这个数就称为"完数".例如6=1+2+3.编程找出1000以内的所有完数. #!/usr/bin/python # -*- ...
- java 第六章 面向对象基础
1.面向对象编程思想 面向过程编程 传统的C语言属于面向过程编程.面向过程解决问题的思路:通常是分析出解决问题所需要的步骤,然后用方法把这些步骤一步一步实现,最后一个一个依次调用方法来解决. 面向过程 ...