bzoj4456: [Zjoi2016]旅行者
题目链接
题解
网格图,对于图分治,每次从中间切垂直于长的那一边,
对于切边上的点做最短路,合并在图两边的答案。
有点卡常
代码
#include<queue>
#include<cctype>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9')c = getchar();
while(c <= '9' && c >= '0') x = x * 10 + c - '0', c = getchar();
return x * f;
}
#define rg register
const int maxn = 100005;
int n,m,tot = 0,ans[maxn];
int X[maxn],Y[maxn];
struct node {
int v,next,w;
} edge[20005 << 2];
int head[maxn],num = 0;
inline void add_edge(int u,int v,int w) {
edge[++ num].v = v;edge[num].w = w; edge[num].next = head[u];head[u] = num;
edge[++ num].v = u;edge[num].w = w; edge[num].next = head[v];head[v] = num;
}
inline int id(rg int a,rg int b){return (a - 1) * m + b; }
struct Question {
int x,y,x1,y1,id;
} q[maxn],p[maxn];
int dis[maxn];
#define mp std::make_pair
#define pr std::pair<int,int>
bool vis[maxn];
std::priority_queue<pr> Q;
void dij(int x,int limx,int limy,int limx1,int limy1) {
for(int i = 1;i <= n;++ i) for(int j = 1;j <= m;++ j)
vis[id(i,j)] = 0,dis[id(i,j)] = 0x3f3f3f3f;
dis[x] = 0;
Q.push(mp(0,x));
while(!Q.empty()) {
int u = Q.top().second; Q.pop();
if(vis[u]) continue;
vis[u] = true;
for(int i = head[u];i;i = edge[i].next) {
int v = edge[i].v;
if(dis[v] > dis[u] + edge[i].w && X[v] >= limx && X[v] <= limx1 && Y[v] <= limy1 && Y[v] >= limy)
dis[v] = edge[i].w + dis[u],Q.push(mp(-dis[v],v));
}
}
}
void solve(int x,int y,int x1,int y1,int l,int r) {
if(l > r) return ;
if(x1 - x > y1 - y) {
int mid = x + x1 >> 1;
for(int i = y;i <= y1 ;++ i) {
dij(id(mid,i),x,y,x1,y1);
for(int j = l;j <= r;++ j)
ans[q[j].id] = std::min(ans[q[j].id],dis[id(q[j].x,q[j].y)] + dis[id(q[j].x1,q[j].y1)]);
}
int L = l - 1,R = r + 1;
for(int i = l;i <= r;++ i) {
if(q[i].x < mid && q[i].x1 < mid)p[++ L] = q[i];
else if(q[i].x > mid && q[i].x1 > mid) p[-- R] = q[i];
}
for(int i = l ;i <= L;++ i) q[i] = p[i];
for(int i = R ;i <= r;++ i) q[i] = p[i];
solve(x,y,mid - 1,y1,l,L); solve(mid + 1,y,x1,y1,R,r);
} else {
int mid = y + y1 >> 1;
for(int i = x;i <= x1 ;++ i) {
dij(id(i,mid),x,y,x1,y1);
for(int j = l;j <= r;++ j)
ans[q[j].id] = std::min(ans[q[j].id],dis[id(q[j].x,q[j].y)] + dis[id(q[j].x1,q[j].y1)]);
}
int L = l - 1,R = r + 1;
for(int i = l;i <= r;++ i) {
if(q[i].y < mid && q[i].y1 < mid)p[++ L] = q[i];
else if(q[i].y > mid && q[i].y1 > mid) p[-- R] = q[i];
}
for(int i = l ;i <= L;++ i) q[i] = p[i];
for(int i = R ;i <= r;++ i) q[i] = p[i];
solve(x,y,x1,mid - 1,l,L); solve(x,mid + 1,x1,y1,R,r);
}
}
int main() {
//freopen("6.in","r",stdin);
n = read(), m = read();
for(int i = 1;i <= n;++ i) for(int j = 1;j < m;++ j)
add_edge(id(i,j),id(i,j + 1),read());
for(int i = 1;i < n;++ i) for(int j = 1;j <= m;++ j)
add_edge(id(i,j),id(i + 1,j),read());
for(int i = 1;i <= n;++ i) for(int j = 1;j <= m;++ j) X[id(i,j)] = i,Y[id(i,j)] = j;
int T = read();
while(T --) {
Question &a = q[++ tot];
a.x = read(),a.y = read(),a.x1 = read(),a.y1 = read();a.id = tot;
if(a.x == a.x1 && a.y == a.y1) ans[tot] = 0;
else ans[tot] = 0x3f3f3f3f;
}
solve(1,1,n,m,1,tot);
for(int i = 1;i <= tot;++ i) printf("%d\n",ans[i]);
return 0;
}
bzoj4456: [Zjoi2016]旅行者的更多相关文章
- [BZOJ4456] [Zjoi2016]旅行者 分治+最短路
4456: [Zjoi2016]旅行者 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 777 Solved: 439[Submit][Status] ...
- BZOJ4456 ZJOI2016旅行者(分治+最短路)
感觉比较套路,每次在长边中轴线处切一刀,求出切割线上的点对矩形内所有点的单源最短路径,以此更新每个询问,递归处理更小的矩形.因为若起点终点跨过中轴线是肯定要经过的,而不跨过中轴线的则可以选择是否经过中 ...
- [BZOJ4456][ZJOI2016]旅行者:分治+最短路
分析 类似于点分治的思想,只统计经过分割线的最短路,然后把地图一分为二. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(regist ...
- 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路
[BZOJ4456][Zjoi2016]旅行者 Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形 ...
- 【BZOJ-4456】旅行者 分治 + 最短路
4456: [Zjoi2016]旅行者 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 254 Solved: 162[Submit][Status] ...
- 【BZOJ4456】旅行者(最短路,分治)
[BZOJ4456]旅行者(最短路,分治) 题面 BZOJ Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北 的道路,这些 ...
- 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 ...
- luogu3350 [ZJOI2016]旅行者
链接 P3350 [ZJOI2016]旅行者 题目大意:给出网格图,求两点之间最短路,多组询问. \(n*m\leq10^5\ \ q\leq 10^5\) 考虑\(CDQ\)分治. 首先把询问离线, ...
随机推荐
- Hadoop基础-MapReduce的Combiner用法案例
Hadoop基础-MapReduce的Combiner用法案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编写年度最高气温统计 如上图说所示:有一个temp的文件,里面存放 ...
- hdu 2433 Travel
http://acm.hdu.edu.cn/showproblem.php?pid=2433 题意: 求删除任意一条边后,任意两点对的最短路之和 以每个点为根节点求一个最短路树, 只需要记录哪些边在最 ...
- js拾遗: replace 替换参数
先来看一个简单的例子吧. var str = "123X321".replace("X", "$'"); 替换后的 str 是什么呢?是 & ...
- 本日吐槽!“人傻钱多”的P2P公司是否是程序员的合适选择(群聊天记录的娱乐)
这个题目“P2P的职位是否是程序员的合适选择”这个问题本身是没啥可以吐槽的 但是每当我们讨论那种类型的公司工资愿意给前端工程师开的最高的时候,P2P这个行业被第一个提出了 目前我收到过面试的企业类型千 ...
- CSS-3 Transition 的使用
css的transition允许css的属性值在一定的时间区间内平滑地过渡.这种效果可以在鼠标单击.获得焦点.被点击或对元素任何改变中触发,并圆滑地以动画效果改变CSS的属性值." tran ...
- leaflet-velocity 参数
本文地址: https://www.cnblogs.com/veinyin/p/10769611.html leaflet-velocity 是 leaflet 绘制风场的一个插件,其控制参数如下所 ...
- mybatis批量增加与删除——(十五)
1.首先应该明白,mybatis增删改返回值是int型的影响行数的值 mapper接口 package cn.xm.mapper; import java.util.List; import cn.x ...
- CentOS安装SVN客户端
1.检查系统是否已经安装如果安装就卸载 rpm -qa subversion yum remove subversion 2.安装 yum install subversion 3.建立SVN库 mk ...
- swapper进程【转】
转自:https://blog.csdn.net/qq_27357145/article/details/80462292 LINUX进程小结 id为0的进程通常是调度进程,常常被称为交换进程(swa ...
- 使用java如何操作elasticsearch?简单示例。
在线API:https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.4/transport-client.html教程:http ...