Luogu3350 ZJOI2016 旅行者 最短路、分治
题意:给出一个$N \times M$的网格图,边有边权,$Q$组询问,每组询问$(x_1,y_1)$到$(x_2,y_2)$的最短路。$N \times M \leq 2 \times 10^4 , Q \leq 10^5$
BZOJ原题竟然没有数据范围
矩形的多组询问问题考虑分治。考虑计算矩形$(x_1,y_1,x_2,y_2)$的询问,我们将较长边沿着中线劈成两半,在这些询问里面就只可能存在两种情况:①询问的两个端点在中线两边,那么路径就一定会经过中线上一点;②询问的两个端点在中线的同一边,那么有可能不会经过中线,也有可能经过中线。所以我们对中线上所有的点跑一边整个矩形的最短路,每一次跑完最短路就更新所有的询问,然后再递归进入两侧矩形回答②类型的询问。时间复杂度似乎是$O(NM \times \sqrt{NM} \times log(NM))$
在$Luogu$题解上学到的一个加速方法:从一个点的最短路转移到新的点跑最短路的时候,可以不将最短路数组赋值为极大值,而是赋值为这一个点经过上一个计算的点到达所有目标点的答案。
(然而还是在Luogu不开O2的情况下TLE)
// luogu-judger-enable-o2
//This code is written by Itst
#include<bits/stdc++.h>
#define pos(i,j) ((i-1)*M+j)
using namespace std; inline int read(){
int a = ;
bool f = ;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ '');
c = getchar();
}
return f ? -a : a;
} const int MAXN = ;
int cntEd , N , M , Q , minDis[MAXN] , ans[MAXN] , head[MAXN];
struct Edge{
int end , upEd , w;
}Ed[MAXN << ];
struct query{
int sx , sy , ex , ey , ind;
}now[MAXN] , pot[MAXN];
priority_queue < pair < int , int > > q; inline void addEd(int a , int b , int c){
Ed[++cntEd].end = b;
Ed[cntEd].w = c;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
} void Dijk(int bx , int by , int lx , int ly , int rx , int ry , int l){
int temp = minDis[pos(bx , by)];
for(int i = lx ; i <= rx ; i++)
for(int j = ly ; j <= ry ; j++)
minDis[pos(i , j)] = l == ? 0x3f3f3f3f : minDis[pos(i , j)] + temp;
minDis[pos(bx , by)] = ;
q.push(make_pair( , pos(bx , by)));
while(!q.empty()){
pair < int , int > t = q.top();
q.pop();
if(minDis[t.second] != -t.first)
continue;
for(int i = head[t.second] ; i ; i = Ed[i].upEd)
if(minDis[Ed[i].end] > minDis[t.second] + Ed[i].w){
minDis[Ed[i].end] = minDis[t.second] + Ed[i].w;
q.push(make_pair(-minDis[Ed[i].end] , Ed[i].end));
}
}
} void solve(int lx , int ly , int rx , int ry , int ql , int qr){
if(ql > qr)
return;
if(rx - lx > ry - ly){
int mid = lx + rx >> ;
for(int i = ly ; i <= ry ; i++){
Dijk(mid , i , lx , ly , rx , ry , i - ly);
for(int j = ql ; j <= qr ; j++)
ans[now[j].ind] = min(ans[now[j].ind] , minDis[pos(now[j].sx , now[j].sy)] + minDis[pos(now[j].ex , now[j].ey)]);
}
int p1 = ql , p2 = qr;
for(int i = ql ; i <= qr ; i++)
if(now[i].sx < mid && now[i].ex < mid)
pot[p1++] = now[i];
else
if(now[i].sx > mid && now[i].ex > mid)
pot[p2--] = now[i];
memcpy(now + ql , pot + ql , sizeof(query) * (qr - ql + ));
solve(lx , ly , mid , ry , ql , p1 - );
solve(mid + , ly , rx , ry , p2 + , qr);
}
else{
int mid = ly + ry >> ;
for(int i = lx ; i <= rx ; i++){
Dijk(i , mid , lx , ly , rx , ry , i - lx);
for(int j = ql ; j <= qr ; j++)
ans[now[j].ind] = min(ans[now[j].ind] , minDis[pos(now[j].sx , now[j].sy)] + minDis[pos(now[j].ex , now[j].ey)]);
}
int p1 = ql , p2 = qr;
for(int i = ql ; i <= qr ; i++)
if(now[i].sy < mid && now[i].ey < mid)
pot[p1++] = now[i];
else
if(now[i].sy > mid && now[i].ey > mid)
pot[p2--] = now[i];
memcpy(now + ql , pot + ql , sizeof(query) * (qr - ql + ));
solve(lx , ly , rx , mid , ql , p1 - );
solve(lx , mid + , rx , ry , p2 + , qr);
}
} int main(){
#ifdef LG
freopen("3350.in" , "r" , stdin);
freopen("3350.out" , "w" , stdout);
#endif
memset(ans , 0x3f , sizeof(ans));
N = read();
M = read();
for(int i = ; i <= N ; i++)
for(int j = ; j < M ; j++){
int t = read();
addEd(pos(i , j) , pos(i , j + ) , t);
addEd(pos(i , j + ) , pos(i , j) , t);
}
for(int i = ; i < N ; i++)
for(int j = ; j <= M ; j++){
int t = read();
addEd(pos(i , j) , pos(i + , j) , t);
addEd(pos(i + , j) , pos(i , j) , t);
}
Q = read();
for(int i = ; i <= Q ; i++){
now[i].sx = read();
now[i].sy = read();
now[i].ex = read();
now[i].ey = read();
now[i].ind = i;
}
solve( , , N , M , , Q);
for(int i = ; i <= Q ; i++)
printf("%d\n" , ans[i]);
return ;
}
Luogu3350 ZJOI2016 旅行者 最短路、分治的更多相关文章
- luogu3350 [ZJOI2016]旅行者
链接 P3350 [ZJOI2016]旅行者 题目大意:给出网格图,求两点之间最短路,多组询问. \(n*m\leq10^5\ \ q\leq 10^5\) 考虑\(CDQ\)分治. 首先把询问离线, ...
- [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条从南到北的道路,这些道路两两相交形 ...
- bzoj4456: [Zjoi2016]旅行者
题目链接 bzoj4456: [Zjoi2016]旅行者 题解 网格图,对于图分治,每次从中间切垂直于长的那一边, 对于切边上的点做最短路,合并在图两边的答案. 有点卡常 代码 #include< ...
- 4456: [Zjoi2016]旅行者
4456: [Zjoi2016]旅行者 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 分析: 每次对当前矩阵按长边化一条分治线,然后在对分 ...
- P3350 [ZJOI2016]旅行者
题目描述 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n*m个路口 (i,j)(1<=i<=n,1&l ...
- BZOJ4456/UOJ#184[Zjoi2016]旅行者 分治 最短路
原文链接http://www.cnblogs.com/zhouzhendong/p/8682133.html 题目传送门 - BZOJ4456 题目传送门 - UOJ#184 题意 $n\times ...
- [BZOJ4456][ZJOI2016]旅行者:分治+最短路
分析 类似于点分治的思想,只统计经过分割线的最短路,然后把地图一分为二. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(regist ...
- BZOJ4456 ZJOI2016旅行者(分治+最短路)
感觉比较套路,每次在长边中轴线处切一刀,求出切割线上的点对矩形内所有点的单源最短路径,以此更新每个询问,递归处理更小的矩形.因为若起点终点跨过中轴线是肯定要经过的,而不跨过中轴线的则可以选择是否经过中 ...
随机推荐
- LVS主从部署配置和使用
LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一. LVS是L ...
- SQLServer Management Studio登录框中的“服务器名”填写
SQL Server Management Studio登录框中的“服务器名”填写 by:授客 QQ:1033553122 打开MSSQL Management Studio,如图,登录框中怎么填写? ...
- Android RecycleView 自定义Item的使用
自定义布局的RecycleView需要自己实现Adapter,ViewHolder和布局: 自定义Adapter继承RecycleView.Adapter,重写getItemCount(),onBin ...
- Android View体系(二)实现View滑动的六种方法
1.View的滑动简介 View的滑动是Android实现自定义控件的基础,同时在开发中我们也难免会遇到View的滑动的处理.其实不管是那种滑动的方式基本思想都是类似的:当触摸事件传到View时,系统 ...
- LoadRunner11录制脚本出现的问题
问题一:无法启动IE浏览器 原因:设置录制程序的录制填写错误,因为IE有两个一个是32位的一个是64位的 我们需要设置浏览器为IE 32位即可正常运行 问题二:无法录制百度等官网页面 原因:录制选项中 ...
- 网页html随机切换背景图片
首先要准备一些图像,图像的大小(无论是尺寸大小还是数据大小)要控制好,如果太大,会使用户等不及查看全图就跳出了,如果太小,又会影响页面质量. 在script中将这些图像编为一个数组,便于调用.数组的长 ...
- 利用搜狐新闻语料库训练100维的word2vec——使用python中的gensim模块
关于word2vec的原理知识参考文章https://www.cnblogs.com/Micang/p/10235783.html 语料数据来自搜狐新闻2012年6月—7月期间国内,国际,体育,社会, ...
- Linux Regulator Framework(2)_regulator driver
转自蜗窝科技:http://www.wowotech.net/pm_subsystem/regulator_driver.html 说实话,这篇好难懂啊... 1. 前言 本文从regulator d ...
- [MapReduce_5] MapReduce 中的 Combiner 组件应用
0. 说明 Combiner 介绍 && 在 MapReduce 中的应用 1. 介绍 Combiner: Map 端的 Reduce,有自己的使用场景 在相同 Key 过多的情况下 ...
- Eclipse配置和使用Maven
一.ecplise配置Maven 1.下载eclipse的Maven插件.(有些eclipse版本中已经集成了此Maven插件,可以不用下载). 需要下载m2eclipse插件. 2.安装m2ecli ...