题目

给定一张\(n*m\)的网格图,\(q\)次询问两点之间距离

\(n*m\leq 2*10^4,q\leq 10^5\)


分析

首先floyd会TLE,考虑两点间距离可以由两段拼凑起来,

那么枚举中间点然后跑单源最短路,但是这样与floyd时间复杂度无异,

一些中间点实际上完全不需要,考虑分治,每次选取中线上的点在子图内跑单源最短路

据说时间复杂度是\(O(nm\sqrt{nm}\log{nm})\)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=20011,inf=0x3f3f3f3f; struct node{int y,w,next;}e[N<<2];
struct rec{int lx,ly,rx,ry,rk;}q[N*5],q1[N*5],q2[N*5];
struct Two{
int d,x;
inline bool operator <(const Two &t)const{
return d<t.d;
}
};
int as[N],Cnt,et=1,Q,dis[N],ans[N*5],n,m,Lx,Ly,Rx,Ry; Two heap[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void add(int x,int y,int w){
e[++et]=(node){y,w,as[x]},as[x]=et;
e[++et]=(node){x,w,as[y]},as[y]=et;
}
inline signed min(int a,int b){return a<b?a:b;}
inline void Push(Two w){
heap[++Cnt]=w;
rr int x=Cnt;
while (x>1){
if (heap[x]<heap[x>>1])
swap(heap[x],heap[x>>1]),x>>=1;
else return;
}
}
inline void Pop(){
heap[1]=heap[Cnt--];
rr int x=1;
while ((x<<1)<=Cnt){
rr int y=x<<1;
if (y<Cnt&&heap[y+1]<heap[y]) ++y;
if (heap[y]<heap[x]) swap(heap[x],heap[y]),x=y;
else return;
}
}
inline signed rk(int x,int y){return (x-1)*m+y;}
inline bool Into(int Rk){
rr int x=(Rk-1)/m+1,y=Rk-(x-1)*m;
return Lx<=x&&x<=Rx&&Ly<=y&&y<=Ry;
}
inline void Dijkstra(int S){
if (dis[S]){
for (rr int i=Lx;i<=Rx;++i)
for (rr int j=Ly;j<=Ry;++j)
if (rk(i,j)!=S) dis[rk(i,j)]+=dis[S];
}else for (rr int i=Lx;i<=Rx;++i)
for (rr int j=Ly;j<=Ry;++j)
dis[rk(i,j)]=inf;
heap[++Cnt]=(Two){0,S},dis[S]=0;
while (Cnt){
rr Two t=heap[1];
Pop(); if (t.d!=dis[t.x]) continue;
for (rr int i=as[t.x];i;i=e[i].next)
if (Into(e[i].y)&&dis[e[i].y]>dis[t.x]+e[i].w){
dis[e[i].y]=dis[t.x]+e[i].w;
Push((Two){dis[e[i].y],e[i].y});
}
}
}
inline void dfs(int lx,int rx,int ly,int ry,int l,int r){
if (l>r) return;
if (lx==rx&&ly==ry){
for (rr int i=l;i<=r;++i) ans[q[i].rk]=0;
return;
}
Lx=lx,Rx=rx,Ly=ly,Ry=ry;
if (rx-lx>ry-ly){
rr int mid=(lx+rx)>>1,tot1=0,tot2=0;
for (rr int i=ly;i<=ry;++i){
Dijkstra(rk(mid,i));
for (rr int j=l;j<=r;++j)
ans[q[j].rk]=min(ans[q[j].rk],dis[rk(q[j].lx,q[j].ly)]+dis[rk(q[j].rx,q[j].ry)]);
}
for (rr int i=l;i<=r;++i){
if (lx<=q[i].lx&&q[i].lx<=mid&&lx<=q[i].rx&&q[i].rx<=mid) q1[++tot1]=q[i];
if (mid+1<=q[i].lx&&q[i].lx<=rx&&mid+1<=q[i].rx&&q[i].rx<=rx) q2[++tot2]=q[i];
}
for (rr int i=1;i<=tot1;++i) q[i+l-1]=q1[i];
for (rr int i=1;i<=tot2;++i) q[r-i+1]=q2[i];
dfs(lx,mid,ly,ry,l,l+tot1-1);
dfs(mid+1,rx,ly,ry,r-tot2+1,r);
}else{
rr int mid=(ly+ry)>>1,tot1=0,tot2=0;
for (rr int i=lx;i<=rx;++i){
Dijkstra(rk(i,mid));
for (rr int j=l;j<=r;++j)
ans[q[j].rk]=min(ans[q[j].rk],dis[rk(q[j].lx,q[j].ly)]+dis[rk(q[j].rx,q[j].ry)]);
}
for (rr int i=l;i<=r;++i){
if (ly<=q[i].ly&&q[i].ly<=mid&&ly<=q[i].ry&&q[i].ry<=mid) q1[++tot1]=q[i];
if (mid+1<=q[i].ly&&q[i].ly<=ry&&mid+1<=q[i].ry&&q[i].ry<=ry) q2[++tot2]=q[i];
}
for (rr int i=1;i<=tot1;++i) q[i+l-1]=q1[i];
for (rr int i=1;i<=tot2;++i) q[r-i+1]=q2[i];
dfs(lx,rx,ly,mid,l,l+tot1-1);
dfs(lx,rx,mid+1,ry,r-tot2+1,r);
}
}
signed main(){
n=iut(),m=iut();
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<m;++j)
add(rk(i,j),rk(i,j+1),iut());
for (rr int i=1;i<n;++i)
for (rr int j=1;j<=m;++j)
add(rk(i,j),rk(i+1,j),iut());
Q=iut();
for (rr int i=1;i<=Q;++i)
ans[i]=inf,q[i]=(rec){iut(),iut(),iut(),iut(),i};
dfs(1,n,1,m,1,Q);
for (rr int i=1;i<=Q;++i) print(ans[i]),putchar(10);
return 0;
}

#分治,Dijkstra#洛谷 3350 [ZJOI2016]旅行者的更多相关文章

  1. 洛谷P3348 [ZJOI2016]大森林(LCT,虚点,树上差分)

    洛谷题目传送门 思路分析 最简单粗暴的想法,肯定是大力LCT,每个树都来一遍link之类的操作啦(T飞就不说了) 考虑如何优化算法.如果没有1操作,肯定每个树都长一样.有了1操作,就来仔细分析一下对不 ...

  2. 洛谷 P3349 [ZJOI2016]小星星 解题报告

    P3349 [ZJOI2016]小星星 题目描述 小\(Y\)是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有\(n\)颗小星星,用\(m\)条彩色的细线串了起来,每条细线连着两颗小星星. 有一 ...

  3. Luogu 3350 [ZJOI2016]旅行者

    BZOJ 4456 听若干个大佬讲过$n$遍终于写掉了. 我把时限基本上跑满了2333…… 分治 + 最短路. 首先我们去分治这个矩形格子,找到一条长边把它对半切,对切开的边上的每一个点跑一遍最短路然 ...

  4. ●洛谷P3348 [ZJOI2016]大森林

    题链: https://www.luogu.org/problemnew/show/P3348 题解: LCT,神题 首先有这么一个结论: 每次的1操作(改变生长点操作),一定只会会对连续的一段区间产 ...

  5. 洛谷P3348 [ZJOI2016]大森林 [LCT]

    传送门 刷了那么久水题之后终于有一题可以来写写博客了. 但是这题太神仙了我还没完全弄懂-- upd:写完博客之后似乎懂了. 思路 首先很容易想到\(O(n^2\log n)\)乘上\(O(\frac{ ...

  6. [洛谷P2605] ZJOI2016 基站选址

    问题描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄不超过Si的范 ...

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

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

  8. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

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

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

  10. 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)

    LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...

随机推荐

  1. 项目实战:Qt+Arm+Fpga医疗肾镜(又名内窥镜)(实时影像、冻结、拍照、白平衡、九宫格、录像、背光调整、硬件光源调整、光源手动自动调整、物理按键)

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/111241205长期持续带来更多项目与技术分享, ...

  2. 推导式,集合推导式,生成器表达式及生成器函数day13

    1.推导式 用一行循环判断遍历处一系列数据的方式 推导式在使用时,只能用for循环和判断,而且判断只能是单项判断 基本语法: lst = [i for i in range(1,51)] print( ...

  3. DataGear 制作支持全国、省、市三级数据钻取效果的地图数据可视化看板

    通过DataGear的参数化数据集.图表联动和看板API功能,可以很方便地制作支持数据钻取效果的数据可视化看板. 首先,以上级地区名为参数,新建一个参数化SQL数据集: SELECT COL_NAME ...

  4. 【Azure 环境】使用Azure中的App Service部署Web应用,以Windows为主机系统是否可以启动防病毒,防恶意软件服务呢(Microsoft Antimalware)?

    问题描述 使用Azure中的App Service部署Web应用,以Windows为主机系统是否可以启动防病毒,防恶意软件服务呢? Microsoft Antimalware for Azure is ...

  5. 树莓派修改根文件系统为f2fs

    目录 前言 操作简述 我的实际操作步骤 1. 准备 2. 查看树莓派分区信息 3. 备份根分区 4. 格式化树莓派TF卡根分区为f2fs文件系统 5.恢复备份 前言 在TF卡.固态硬盘之类的nand存 ...

  6. Java 演示线程的死锁问题

    1 package bytezero.deadlock; 2 3 /** 4 * 演示线程的死锁问题: 5 * 6 * 1.死锁的理解:不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃 7 ...

  7. 淘宝电商api接口 获取商品详情 搜索商品

    iDataRiver平台 https://www.idatariver.com/zh-cn/ 提供开箱即用的taobao淘宝电商数据采集API,供用户按需调用. 接口使用详情请参考淘宝接口文档 接口列 ...

  8. Git 常用的基础命令

    #克隆项目到本地.url:项目的git地址:local_dir_name:克隆项目到本地的目录名称,如果不写就默认是git项目中的目录名称 git clone <url> <loca ...

  9. 序列图 时序图 PlantUML vscode drawio 制作

    序列图 时序图 PlantUML vscode drawio 制作 需求 最近发现 序列图 很多文档都用到,而且很好用.经过研究用vscode,idea都可以编写.这里用vscode编写比较简单. d ...

  10. mikumikudance 和 pmxEditor 都可以打开 pmx

    mikumikudance 和 pmxEditor 都可以打开 pmx 模型下载 https://www.bilibili.com/blackboard/activity-5hkwDIRkBv.htm ...