题面

https://www.lydsy.com/JudgeOnline/problem.php?id=4456

题解

分治

设当前work的区间为(x1,y1,x2,y2)

我们将长边分成两半

不妨设长边是(x1,x2)

那么令mid=(x1+x2)/2

对于分界线(mid,y1)~(mid,y2)的所有点 我们做最短路

得到分界线上所有点到区间里任意点的最短路

那么对于询问(sx,sy,tx,ty) 我们可以枚举分界线上某一点(mid,y) 并且用dist((mid,y),(sx,sy))+dist((mid,y),(tx,ty))更新答案

然后对于(sx,sy)和(tx,ty)都落在分界线同一侧的询问我们递归求解

这样做的正确性:每一组询问,一定会经过某次的分界线,在计算到这条分界线的时候就可以算到答案

复杂度:T(n)=4T(n/2)+O(n*(m+nlogm))  m为边数也就是n^2

那么T(n)=n^3(这是n约等于m的情况) 可以通过这道题

n和m差距大的时候更快

Code

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll; ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} const int maxn=;
int n,m,q;
int a[][maxn],b[][maxn];
bool vis[][maxn];
bool flag;
int res[]; struct P{
int x;
pair<int,int> y;
bool operator <(const P &a) const{
return x>a.x;
}
}; priority_queue<P> pq; struct query{
int a,b,c,d;
int p,ans;
void input(){
a=read(),b=read(),c=read(),d=read();
}
} que[]; int dis[][maxn];
int num[][maxn]; void update(int nwx,int nwy,int nwdis){
//cout<<nwx<<' '<<nwy<<' '<<nwdis<<endl;
if(dis[nwx][nwy]>nwdis){
dis[nwx][nwy]=nwdis;
pq.push(P{nwdis,make_pair(nwx,nwy)});
}
}
void doit(int x,int y,int X1,int Y1,int X2,int Y2){
//cout<<X1<<' '<<Y1<<' '<<X2<<' '<<Y2<<' '<<x<<' '<<y<<endl;
for(int i=X1;i<=X2;i++)
for(int j=Y1;j<=Y2;j++)
dis[i][j]=1e9,vis[i][j]=;
dis[x][y]=;
pq.push(P{,make_pair(x,y)});
while(!pq.empty()){
P nw=pq.top();
pq.pop();
int X=nw.y.first,Y=nw.y.second;
//cout<<X<<' '<<Y<<' '<<dis[X][Y]<<endl;
if(vis[X][Y]) continue;
vis[X][Y]=;int dist=dis[X][Y];
if(X>X1) update(X-,Y,dist+b[X-][Y]);
if(X<X2) update(X+,Y,dist+b[X][Y]);
if(Y>Y1) update(X,Y-,dist+a[X][Y-]);
if(Y<Y2) update(X,Y+,dist+a[X][Y]);
}
} void solve(int nwa,int nwb,int nwc,int nwd,int l,int r){
//cout<<nwa<<' '<<nwb<<' '<<nwc<<' '<<nwd<<endl;
if(l>r) return;
int len1=nwc-nwa+,len2=nwd-nwb+;
if(len1>=len2){
int md=(nwa+nwc)>>;
for(int j=nwb;j<=nwd;j++){
doit(md,j,nwa,nwb,nwc,nwd);
for(int k=l;k<=r;k++){
//cout<<que[k].p<<' '<<dis[que[k].a][que[k].b]<<' '<<dis[que[k].c][que[k].d]<<endl;
que[k].ans=min(que[k].ans,dis[que[k].a][que[k].b]+dis[que[k].c][que[k].d]);
}
}
if(nwa<md){
int pos=l-;
for(int i=l;i<=r;i++){
if(que[i].a<md && que[i].c<md) pos++,swap(que[i],que[pos]);
}
solve(nwa,nwb,md-,nwd,l,pos);
}
if(md<nwc){
int pos=l-;
for(int i=l;i<=r;i++){
if(que[i].a>md && que[i].c>md) pos++,swap(que[i],que[pos]);
}
solve(md+,nwb,nwc,nwd,l,pos);
}
}
else{
int md=(nwb+nwd)>>;
for(int i=nwa;i<=nwc;i++){
doit(i,md,nwa,nwb,nwc,nwd);
for(int k=l;k<=r;k++){
//cout<<que[k].p<<' '<<dis[que[k].a][que[k].b]<<' '<<dis[que[k].c][que[k].d]<<endl;
que[k].ans=min(que[k].ans,dis[que[k].a][que[k].b]+dis[que[k].c][que[k].d]);
}
}
if(nwb<md){
int pos=l-;
for(int i=l;i<=r;i++){
if(que[i].b<md && que[i].d<md) pos++,swap(que[i],que[pos]);
}
solve(nwa,nwb,nwc,md-,l,pos);
}
if(md<nwd){
int pos=l-;
for(int i=l;i<=r;i++){
if(que[i].b>md && que[i].d>md) pos++,swap(que[i],que[pos]);
}
solve(nwa,md+,nwc,nwd,l,pos);
}
}
} int main(){
#ifdef LZT
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
n=read();m=read();
if(n>m) flag=;
for(int i=;i<=n;i++){
for(int j=;j<m;j++){
if(!flag) a[i][j]=read();
else b[j][i]=read();
}
}
for(int i=;i<n;i++){
for(int j=;j<=m;j++){
if(!flag) b[i][j]=read();
else a[j][i]=read();
}
}
q=read();
for(int i=;i<=q;i++){
que[i].input();
if(flag) swap(que[i].a,que[i].b),swap(que[i].c,que[i].d);
que[i].p=i;que[i].ans=2e9;
}
if(flag) swap(n,m); solve(,,n,m,,q); for(int i=;i<=q;i++)
res[que[i].p]=que[i].ans;
for(int i=;i<=q;i++)
printf("%d\n",res[i]);
return ;
} /*
2 2
2
3
6 4
2
1 1 2 2
1 2 2 1
*/

Review

分治还是比较明显的

然而数据的处理十分麻烦

因为条件是n×m的范围

所以我们得同时考虑n=m和n>>m的情况

代码中的处理方法是跟别人学的 很棒棒 要多写几遍

bzoj 4456 [Zjoi2016]旅行者的更多相关文章

  1. BZOJ.4456.[ZJOI2016]旅行者(分治 Dijkstra)

    题目链接 \(Description\) 给定\(n\times m\)的带边权网格图.\(Q\)次询问从点\((x_i,y_i)\)到点\((x_j,y_j)\)的最短路. \(n\times m\ ...

  2. 4456: [Zjoi2016]旅行者

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

  3. ●BOZJ 4456 [Zjoi2016]旅行者

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4456 题解: 分治好题.大致做法如下:对于一开始的矩形区域,过较长边的中点把矩形区域分为两个 ...

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

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

  5. P3350 [ZJOI2016]旅行者

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

  6. bzoj4456: [Zjoi2016]旅行者

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

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

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

  8. Luogu 3350 [ZJOI2016]旅行者

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

  9. luogu3350 [ZJOI2016]旅行者

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

随机推荐

  1. 关于HTTP1.1的长连接

    HTTP是一个构建在传输层的TCP协议之上的应用层的协议,在这个层的协议,是一种网络交互须要遵守的一种协议规范. HTTP1.0的短连接 HTTP 1.0规定浏览器与server仅仅保持短暂的连接.浏 ...

  2. 十天学习PHP之第二天

    学习目的:学会构建数据库  在ASP中,假设是ACCESS数据库你能够直接打开ACCESS来编辑MDB文件,假设是SQL SERVER你能够打开企业管理器来编辑SQL SERVER数据库.可是在PHP ...

  3. FZUOJ Problem 2200 cleaning DP

    Problem 2200 cleaning  Problem Description N个人围成一圈在讨论大扫除的事情,需要选出K个人.但是每个人与他距离为2的人存在矛盾,所以这K个人中任意两个人的距 ...

  4. Mac OS用docker Desktop安装单节点kubernetes

    方案: 安装方式:阿里云minikube,k8s官方minikube,kubeadm, docker Desktop中自带第k8s 安装环境:在linux虚拟机中安装k8s,在macos中安装k8s, ...

  5. LOJ#139. 树链剖分

    LOJ#139. 树链剖分 题目描述 这是一道模板题. 给定一棵$n$个节点的树,初始时该树的根为 1 号节点,每个节点有一个给定的权值.下面依次进行 m 个操作,操作分为如下五种类型: 换根:将一个 ...

  6. ActiveMQ 安全认证

    修改配置文件 位置: apache-activemq-5.9.0/conf/ vi activemq.xml 在<broker xmlns="http://activemq.apach ...

  7. oracle 删除用户命令和部分表空间操作

    删除用户 drop user user_name cascade; 建立表空间 CREATE TABLESPACE data01DATAFILE '/oracle/oradata/db/DATA01. ...

  8. 让振动器振动起来——Vibrator的使用

    AndroidManifest.xml 获取系统权限 <uses-permission android:name="android.permission.VIBRATE"/& ...

  9. 最大网络流 EK 算法

    网络流是什么类型的问题,看一道题目你就知道了 点击打开链接 . 默认具备图论的基本知识,网络流概念比较多,先看看书熟悉一下那些概念.比较好!一个寄出的网络最大流.EK算法写的. 这是一幅网络,求S   ...

  10. maven实战(7)-- 设置maven编译器级别

    两种方式: (一)全局设置 首先我们要在settings.xml文件中找到<profiles>标签,然后在此标签内部粘贴如下配置: <profile> <id>jd ...