传送门

题意:给出一个$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 旅行者 最短路、分治的更多相关文章

  1. luogu3350 [ZJOI2016]旅行者

    链接 P3350 [ZJOI2016]旅行者 题目大意:给出网格图,求两点之间最短路,多组询问. \(n*m\leq10^5\ \ q\leq 10^5\) 考虑\(CDQ\)分治. 首先把询问离线, ...

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

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

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

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

  4. bzoj4456: [Zjoi2016]旅行者

    题目链接 bzoj4456: [Zjoi2016]旅行者 题解 网格图,对于图分治,每次从中间切垂直于长的那一边, 对于切边上的点做最短路,合并在图两边的答案. 有点卡常 代码 #include< ...

  5. 4456: [Zjoi2016]旅行者

    4456: [Zjoi2016]旅行者 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 分析: 每次对当前矩阵按长边化一条分治线,然后在对分 ...

  6. P3350 [ZJOI2016]旅行者

    题目描述 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n*m个路口 (i,j)(1<=i<=n,1&l ...

  7. BZOJ4456/UOJ#184[Zjoi2016]旅行者 分治 最短路

    原文链接http://www.cnblogs.com/zhouzhendong/p/8682133.html 题目传送门 - BZOJ4456 题目传送门 - UOJ#184 题意 $n\times ...

  8. [BZOJ4456][ZJOI2016]旅行者:分治+最短路

    分析 类似于点分治的思想,只统计经过分割线的最短路,然后把地图一分为二. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(regist ...

  9. BZOJ4456 ZJOI2016旅行者(分治+最短路)

    感觉比较套路,每次在长边中轴线处切一刀,求出切割线上的点对矩形内所有点的单源最短路径,以此更新每个询问,递归处理更小的矩形.因为若起点终点跨过中轴线是肯定要经过的,而不跨过中轴线的则可以选择是否经过中 ...

随机推荐

  1. SoapUI SoapUI测试WebService协议接口简介

    SoapUI测试WebService协议接口简介 by:授客 QQ:1033553122 1. 创建项目,入口:File -> New SOAP Project,或者右键默认项目Project- ...

  2. Linux 学习笔记之超详细基础linux命令 Part 7

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 6----------------- ...

  3. (网页)javaScript增删改查(转)

    转自CSDN: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> ...

  4. MagicApp说明

    title: MagicApp说明 date: 2017-12-06 05:41:00 tags: IT 技术 MagicApp是日常处理的程序,协助进行日常工作处理 批量重命名模块 说明 该模块是根 ...

  5. [20171225]没有备份数据文件的恢复.txt

    [20171225]没有备份数据文件的恢复.txt --//别人问的问题,增加了数据文件没有备份,如何恢复,实际上很简单,因为当前控制文件有记录建立时间只要从建立数据文件开始的--//归档日志都存在恢 ...

  6. webrtc 实时视频 .net websocket信令服务器

    这篇文章主要参考了 Webrtc WebSocket实现音视频通讯,非常感谢提供代码 前端部分完全是从这篇文章复制过来的,只是修改了webscket的url,还有加入了webrtc-adapterjs ...

  7. 成功激活Win8.1专业版方法

    前两天安装了Win8.1,感觉界面效果都很简约,速度很快,很喜欢,但是不是破解版,本想将就着用,等到真正破解工具出来了再激活,但是用了两天发现系统右下角屏幕上有未激活的提示,时常弹出激活设置,看着有点 ...

  8. Luogu P4707 重返现世

    题目描述 为了打开返回现世的大门,Yopilla 需要制作开启大门的钥匙.Yopilla 所在的迷失大陆有 \(n\) 种原料,只需要集齐任意 \(k\) 种,就可以开始制作. Yopilla 来到了 ...

  9. oc kvc的模式:匹配搜索模式(模式匹配)、装包解包

    按照一定规则使用匹配模式在目标空间进行搜索,然后执行相应操作: 运行时系统将kvc的运行机制解释为模式匹配,将值的兼容性问题解释为装包解包问题 一.模式匹配 The default implement ...

  10. QT获取窗口大小和位置等信息

    QT窗口尺寸,窗口大小和大小改变引起的事件 QResizeEvent. 来源:http://blog.csdn.net/dbzhang800/article/details/6741344?reloa ...