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\)分治. 首先把询问离线, ...
随机推荐
- ajax实现输入用户名异步提示是否可用
<script type="text/javascript"> //页面加载完毕后执行 $(document).ready(function(){ //用户名输入框绑定 ...
- 第一节 Spring的环境搭建
正在构建,扫一扫,敬请期待 和玩得来的人在一起玩才叫玩! 和玩不来的人在一起玩,那种感觉就像加班啊! 关注胖个人微信公众账号,希望对各位学生有所帮助! --胖先生 Spring框架,什么是Sprin ...
- bzoj千题计划191:bzoj2337: [HNOI2011]XOR和路径
http://www.lydsy.com/JudgeOnline/problem.php?id=2337 概率不能异或 但根据期望的线性,可以计算出每一位为1的概率,再累积他们的期望 枚举每一位i,现 ...
- Linux使用imagemagick的convert命令压缩图片、节省服务器空间
一.安装: sudo apt-get install imagemagick 二.说明 imagemagick的命令convert可以完成此任务,其参数-resize用来改变图片尺寸,可以直接指定像素 ...
- 原生JS不到30行,实现类似javascript MVC的功能-minTemplate
严格来讲不能说是MVC,应为模版里不能写逻辑语句. 灵感来源于我的上篇文字:<封装JSON数据转自定义HTML方法parseHTML>: 这里再封装一个简单方法,在保持原来的方便改变不大的 ...
- [译]使用chage来管理Linux密码过期时间的七个例子
本文译自 7 Examples to Manage Linux Password Expiration and Aging Using chage 本文主要介绍命令chage的使用,译文会对原文内容会 ...
- 【干货】Linux内存数据的获取与转存 直捣密码
知识源:Unit 2: Linux/Unix Acquisition 2.1 Linux/Unix Acquistion Memory Acquisition 中的实验demo部分 小白注意,这是网 ...
- Mycat 配置及优化【转】
前言 Mycat 是一个数据库分库分表中间件 MyCAT 是作为通用代理设计的,后端是以 Mysql协议 和 JDBC 的方式连接数据库,可以支持 Oracle.DB2.SQL Server . mo ...
- 【论文阅读】HydraPlus-Net: Attentive Deep Features for Pedestrian Analysis
转载请注明出处:https://www.cnblogs.com/White-xzx/ 原文地址:https://arxiv.org/abs/1709.09930 Github: https://git ...
- sql语句添加查询字段
SELECT * FROM( SELECT ROW_NUMBER() OVER (ORDER BY r.UpdateTime desc) tempRowNum,h.BizID,h.OrgID FROM ...