luogu3350 [ZJOI2016]旅行者
链接 P3350 [ZJOI2016]旅行者
- 题目大意:给出网格图,求两点之间最短路,多组询问。
- \(n*m\leq10^5\ \ q\leq 10^5\)
- 考虑\(CDQ\)分治。
- 首先把询问离线,对于一个矩阵中的最短路,如果\(u,v\)不在统一侧,那么一定会经过平分线。
- 所以对矩阵分治理,只考虑最短路经过矩阵中线的情况,枚举中线上的任意一点做最短路,用\(Dis_u+Dis_v\)更新这次询问的答案即可。
- 然后把询问划分到左右两边的矩阵中去,分别递归处理即可。
- 类似于整体二分的思想?
- 代码
// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=150001;
const int M=200001;
const int inf=2e9;
int n,m,tot,q,u,cnt,nt[M],w[M],to[M],hd[N],ans[N];
int X[M],Y[M],vis[M],Dis[M];
struct Qs{int id,s,t;}Q[N],tmp[N];
vector<int>idx[N];
void link(R f,R t,R d){nt[++cnt]=hd[f],to[cnt]=t,w[cnt]=d,hd[f]=cnt;}
int gi(){
R x=0,k=1;char c=getchar();
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')k=-1,c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*k;
}
struct nd{int i,v;};
int operator < (nd x,nd y){return x.v>y.v;}
priority_queue<nd>G;
void dij(R s,R lx,R ly,R rx,R ry){
while(!G.empty())G.pop();
for(R i=lx;i<=rx;++i)
for(R j=ly;j<=ry;++j)
Dis[idx[i][j]]=inf,vis[idx[i][j]]=0;
G.push((nd){s,0});
while(!G.empty()){
R i=G.top().i,D=G.top().v;G.pop();
if(vis[i])continue;vis[i]=1,Dis[i]=D;
for(R k=hd[i];k;k=nt[k])
if(!vis[to[k]]&&lx<=X[to[k]]&&rx>=X[to[k]]&&ly<=Y[to[k]]&&ry>=Y[to[k]])
if(Dis[to[k]]>Dis[i]+w[k]){
Dis[to[k]]=Dis[i]+w[k];
G.push((nd){to[k],Dis[to[k]]});
}
}
}
void Div(R lx,R rx,R ly,R ry,R Le,R Ri){
if(Le>Ri)return ;
if(rx-lx>ry-rx){
R mid=(lx+rx)>>1;
for(R i=ly;i<=ry;++i){
dij(idx[mid][i],lx,ly,rx,ry);
for(R j=Le;j<=Ri;++j)
ans[Q[j].id]=min(ans[Q[j].id],Dis[Q[j].s]+Dis[Q[j].t]);
}
R tp1=Le-1,tp2=Ri+1;
for(R i=Le;i<=Ri;++i){
R u=Q[i].s,v=Q[i].t;
if(X[u]<mid&&X[v]<mid)tmp[++tp1]=Q[i];
if(X[u]>mid&&X[v]>mid)tmp[--tp2]=Q[i];
}
for(R i=Le;i<=Ri;++i)Q[i]=tmp[i];
Div(lx,mid-1,ly,ry,Le,tp1);
Div(mid+1,rx,ly,ry,tp2,Ri);
}
else {
R mid=(ly+ry)>>1;
for(R i=lx;i<=rx;++i){
dij(idx[i][mid],lx,ly,rx,ry);
for(R j=Le;j<=Ri;++j)
ans[Q[j].id]=min(ans[Q[j].id],Dis[Q[j].s]+Dis[Q[j].t]);
}
R tp1=Le-1,tp2=Ri+1;
for(R i=Le;i<=Ri;++i){
R u=Q[i].s,v=Q[i].t;
if(Y[u]<mid&&Y[v]<mid)tmp[++tp1]=Q[i];
if(Y[u]>mid&&Y[v]>mid)tmp[--tp2]=Q[i];
}
for(R i=Le;i<=Ri;++i)Q[i]=tmp[i];
Div(lx,rx,ly,mid-1,Le,tp1);
Div(lx,rx,mid+1,ry,tp2,Ri);
}
}
int main(){
n=gi(),m=gi();
for(R i=1;i<=n;++i){
idx[i].push_back(0);
for(R j=1;j<=m;++j){
idx[i].push_back(++tot);
X[tot]=i,Y[tot]=j;
}
}
for(R i=1;i<=n;++i)
for(R j=1;j<m;++j){
u=gi();
link(idx[i][j],idx[i][j+1],u);
link(idx[i][j+1],idx[i][j],u);
}
for(R i=1;i<n;++i)
for(R j=1;j<=m;++j){
u=gi();
link(idx[i][j],idx[i+1][j],u);
link(idx[i+1][j],idx[i][j],u);
}
q=gi();
for(R i=1;i<=q;++i){
R u=gi(),v=gi(),x=gi(),y=gi();
Q[i]=(Qs){i,idx[u][v],idx[x][y]};
}
memset(ans,63,sizeof(ans));
Div(1,n,1,m,1,q);
for(R i=1;i<=q;++i)printf("%d\n",ans[i]);
return 0;
}
luogu3350 [ZJOI2016]旅行者的更多相关文章
- Luogu3350 ZJOI2016 旅行者 最短路、分治
传送门 题意:给出一个$N \times M$的网格图,边有边权,$Q$组询问,每组询问$(x_1,y_1)$到$(x_2,y_2)$的最短路.$N \times M \leq 2 \times 10 ...
- 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 ...
- ●BOZJ 4456 [Zjoi2016]旅行者
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4456 题解: 分治好题.大致做法如下:对于一开始的矩形区域,过较长边的中点把矩形区域分为两个 ...
- [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 ...
随机推荐
- Ubuntu启动 卡在checking battery state 解决方案
Ubuntu启动,卡在checking battery statALT + F1或者CTRL+ALT+F6切换到命令行[CTRL+ALT+F7返回界面]执行 sudo gdm start后就可以正常登 ...
- 高通Android camera运行流程【转】
本文转载自:http://blog.csdn.net/unicornkylin/article/details/13293295 1.总体架构 Android Camera 框架从整体上看是一个 cl ...
- qbzt day5 下午
农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地.John打算在牧场上的某几格里种上美味的草,供他的奶牛们享 ...
- 【转】Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128)
[转]Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128) ...
- EDM设计案例分享:6款引人入胜的夏日邮件营销模板分享
夏日酷暑,清凉如风.在这个假期,旅游行业.酒店.服饰等都推出不少的假期活动,吸引游者的到来.假日期间,让我们看看一些旅游业.品牌服装店和酒店是怎么做好电子邮件广告的.在此,Focussend精心为大家 ...
- day49—JavaScript阻止浏览器默认行为
转行学开发,代码100天——2018-05-04 今天主要说明一下通过JavaScript对浏览器默认行为的阻止操作.比如右键菜单的行为. 阻止默认行为的语句为: return false; 例如,阻 ...
- 接口自动化之提取响应结果(raw、json)
做接口测试时,我们一般会取得响应结果的部分值,来与预期结果对比,做断言 目录 1.响应结果类型 2.json响应结果的提取 3.raw响应结果的提取 1.响应结果类型 通过fiddler的respon ...
- Android Framework中Thread类
Thread类是Android为线程操作而做的一个封装.代码在Thread.cpp中,其中还封装了一些与线程同步相关的类. Thread类 Thread类的构造函数中的有一个canCallJava T ...
- jmeter逻辑控制详解(1)
逻辑控制器 Jmeter提供了多种逻辑控制器,下面进行讲解说明: 1.Simple Controller 简单控制器是最基本的控制器,对jmeter测试运行没有任何影响,可以将某些请求归集在一个简单控 ...
- 【MM系列】SAP MM中的委外加工与信息记录
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM中的委外加工与信息记录 ...