[ZJOI2016]旅行者
题目描述
小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)最少需要花多少时间。
题解
网格图上多次询问最短路,肯定要离线分治。
CDQ整体二分什么的好像都不太适用。
考虑正在分治一个矩形,我们可以把长的一边切断。
然后把询问分为两种:起点和终点都在一侧、起点终点分居两侧。
分居两侧的情况在把本次分治结束后答案已经更新完了,就把它扔掉就好了。
对于本次分治,我们可以对分治中线上所有点矩形内跑一次最短路,然后对所有询问更新答案。
然后递归分治两边.
然鹅并不会分析复杂度。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 1e8
#define N 100009
#define mm make_pair
using namespace std;
priority_queue<pair<int,int> >q;
int n,m,dis[N],tot,head[N],ans[N];
bool vis[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct edge{int n,to,l;}e[N<<];
struct query{
int xf,yf,xs,ys,id;
}a[N],b[N];
inline void add(int u,int v,int l){
e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=l;
}
inline int calc(int i,int j){return (i-)*m+j;}
inline bool pd(int id,int xf,int xs,int yf,int ys){
int x=(id-)/m+,y=(id-)%m+;
if(x>=xf&&x<=xs&&y>=yf&&y<=ys)return ;else return ;
}
inline void spfa(int s,int xf,int xs,int yf,int ys){
int x=dis[s];
for(int i=xf;i<=xs;++i)
for(int j=yf;j<=ys;++j){
dis[calc(i,j)]+=x;
vis[calc(i,j)]=;
}
q.push(mm(,s));dis[s]=;
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;vis[u]=;
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(!pd(v,xf,xs,yf,ys))continue;
if(dis[v]>dis[u]+e[i].l){
dis[v]=dis[u]+e[i].l;
q.push(mm(-dis[v],v));
}
}
}
}
void solve(int xf,int xs,int yf,int ys,int l,int r){
if(l>r)return;
if(xf==xs&&yf==ys){
for(int i=l;i<=r;++i)ans[a[i].id]=;
return;
}
for(int i=xf;i<=xs;++i)
for(int j=yf;j<=ys;++j)
dis[calc(i,j)]=inf;
if(xs-xf>ys-yf){
int mid=(xf+xs)>>;
for(int i=yf;i<=ys;++i){
spfa(calc(mid,i),xf,xs,yf,ys);
for(int j=l;j<=r;++j)ans[a[j].id]=min(ans[a[j].id],dis[calc(a[j].xf,a[j].yf)]+dis[calc(a[j].xs,a[j].ys)]);
}
int L=l,R=r;
for(int i=l;i<=r;++i){
if(a[i].xf<=mid&&a[i].xs<=mid)b[L++]=a[i];
else if(a[i].xf>mid&&a[i].xs>mid)b[R--]=a[i];
}
for(int i=l;i<=r;++i)a[i]=b[i];
solve(xf,mid,yf,ys,l,L-);solve(mid+,xs,yf,ys,R+,r);
}
else{
int mid=(yf+ys)>>;
for(int i=xf;i<=xs;++i){
spfa(calc(i,mid),xf,xs,yf,ys);
for(int j=l;j<=r;++j)ans[a[j].id]=min(ans[a[j].id],dis[calc(a[j].xf,a[j].yf)]+dis[calc(a[j].xs,a[j].ys)]);
}
int L=l,R=r;
for(int i=l;i<=r;++i){
if(a[i].yf<=mid&&a[i].ys<=mid)b[L++]=a[i];
else if(a[i].yf>mid&&a[i].ys>mid)b[R--]=a[i];
}
for(int i=l;i<=r;++i)a[i]=b[i];
solve(xf,xs,yf,mid,l,L-);solve(xf,xs,mid+,ys,R+,r);
}
}
int main(){
n=rd();m=rd();int x;
for(int i=;i<=n;++i)
for(int j=;j<m;++j){
x=rd();add(calc(i,j),calc(i,j+),x);
}
for(int i=;i<n;++i)
for(int j=;j<=m;++j){
x=rd();add(calc(i,j),calc(i+,j),x);
}
memset(ans,0x3f,sizeof(ans));
int q=rd();
for(int i=;i<=q;++i){
a[i].xf=rd();a[i].yf=rd();a[i].xs=rd();a[i].ys=rd();
a[i].id=i;
}
solve(,n,,m,,q);
for(int i=;i<=q;++i)printf("%d\n",ans[i]);
return ;
}
[ZJOI2016]旅行者的更多相关文章
- bzoj4456: [Zjoi2016]旅行者
题目链接 bzoj4456: [Zjoi2016]旅行者 题解 网格图,对于图分治,每次从中间切垂直于长的那一边, 对于切边上的点做最短路,合并在图两边的答案. 有点卡常 代码 #include< ...
- 4456: [Zjoi2016]旅行者
4456: [Zjoi2016]旅行者 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 分析: 每次对当前矩阵按长边化一条分治线,然后在对分 ...
- [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条从南到北的道路,这些道路两两相交形 ...
- P3350 [ZJOI2016]旅行者
题目描述 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n*m个路口 (i,j)(1<=i<=n,1&l ...
- luogu3350 [ZJOI2016]旅行者
链接 P3350 [ZJOI2016]旅行者 题目大意:给出网格图,求两点之间最短路,多组询问. \(n*m\leq10^5\ \ q\leq 10^5\) 考虑\(CDQ\)分治. 首先把询问离线, ...
- ●BOZJ 4456 [Zjoi2016]旅行者
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4456 题解: 分治好题.大致做法如下:对于一开始的矩形区域,过较长边的中点把矩形区域分为两个 ...
- BZOJ4456/UOJ#184[Zjoi2016]旅行者 分治 最短路
原文链接http://www.cnblogs.com/zhouzhendong/p/8682133.html 题目传送门 - BZOJ4456 题目传送门 - UOJ#184 题意 $n\times ...
- Luogu3350 ZJOI2016 旅行者 最短路、分治
传送门 题意:给出一个$N \times M$的网格图,边有边权,$Q$组询问,每组询问$(x_1,y_1)$到$(x_2,y_2)$的最短路.$N \times M \leq 2 \times 10 ...
随机推荐
- iOS---------显示和隐藏状态栏的网络活动标志
//在向服务端发送请求状态栏显示网络活动标志: [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; ...
- 设计模式系列之过滤器模式(Chriteria Pattern)
过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来.这种类 ...
- SQL Server Mirror 断开后,删除副本上镜像数据库
一般而言,SQL Server 在数据库级别进行数据同步的方式主要有三种 1.日志传送:2.Mirror(镜像):3. AlwaysOn.复制订阅技术理解为表级别的同步,不归结为数据库级别的同步. 在 ...
- 安装ESXi部署OVF详细步骤
整个安装部署过程均在个人环境进行.欧克,我们现在开始. 一.安装ESXi 1.Enter回车 2.Enter回车继续 3.F11,接受继续 4.Enter,回车继续(选择安装ESXi的设备) 5.默认 ...
- SQL数据库一些系统语法含义
昨天在数据库中建立数据表的时候要求显示的添加一些系统语法规则,对于这些设置不知道都是什么含义,这次记录下来供以后学习. (1)SET ANSI_NULLS ON语句 T-SQL支持在与空值进行比较时, ...
- python之sqlalchemy的使用
准备数据 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column from sqla ...
- 基于SVM的鸢尾花数据集分类实现[使用Matlab]
iris数据集的中文名是安德森鸢尾花卉数据集,英文全称是Anderson’s Iris data set.iris包含150个样本,对应数据集的每行数据.每行数据包含每个样本的四个特征和样本的类别信息 ...
- 创建DVWA环境时遇到的问题
前言:我下载了PHP Study,也按照步骤下载保存了DVWA,之后我又按照百度的准备登陆检查是否正确安装DVWA,于是,我登录了百度上查到的链接:http://localhost/DVWA-mast ...
- 27 python 初学(信号量、条件变量、同步条件、队列)
参考博客: www.cnblogs.com/yuanchenqi/articles/5733873.html semaphore 信号量: condition 条件变量: event 同步条件:条件 ...
- 利用SQL注入漏洞登录后台
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询 ...