Luogu 3350 [ZJOI2016]旅行者
BZOJ 4456
听若干个大佬讲过$n$遍终于写掉了。
我把时限基本上跑满了2333……
分治 + 最短路。
首先我们去分治这个矩形格子,找到一条长边把它对半切,对切开的边上的每一个点跑一遍最短路然后更新所有答案,接下来把询问分成两类,一类是两个端点都在切开的中间线一侧的,另一类是在两侧的。对于在中轴线一侧的点,我们把它加到一侧去继续分治,而在中轴线两侧的点就不用继续分治了,因为接下来的中轴线一定不会对它造成影响。
分治边界是没有对应询问的情况和只剩下一个点但是仍然有询问的情况,这时候可以直接用$0$更新当前的答案。
不会算时间复杂度,这篇博客证明是$O(S\sqrt{S}logS)$的,其中$S$代表面积。
另外,听说$spfa$比$dijskra$跑得快……
Code:
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
typedef pair <int, int> pin; const int N = 2e4 + ;
const int M = 1e5 + ;
const int inf = 0x3f3f3f3f; int n, m, qn, tot = , head[N], dis[N], ans[M], verx[N], very[N];
bool vis[N];
priority_queue <pin> Q; struct Edge {
int to, nxt, val;
} e[N << ]; inline void add(int from, int to, int val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} inline void addEdge(int x, int y, int val) {
add(x, y, val), add(y, x, val);
} struct Querys {
int xa, xb, ya, yb, id;
} q[M], tmp[M]; inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline void chkMin(int &x, int y) {
if(y < x) x = y;
} inline int id(int x, int y) {
return (x - ) * m + y;
} void dij(int xl, int xr, int yl, int yr, int stx, int sty) {
for(int i = xl; i <= xr; i++)
for(int j = yl; j <= yr; j++)
dis[id(i, j)] = inf, vis[id(i, j)] = ; dis[id(stx, sty)] = ;
Q.push(pin(, id(stx, sty)));
for(; !Q.empty(); ) {
int x = Q.top().second; Q.pop();
if(vis[x]) continue;
vis[x] = ;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(verx[y] >= xl && verx[y] <= xr && very[y] >= yl && very[y] <= yr) {
if(dis[y] > dis[x] + e[i].val) {
dis[y] = dis[x] + e[i].val;
Q.push(pin(-dis[y], y));
}
}
}
}
} void solve(int xl, int xr, int yl, int yr, int ql, int qr) {
if(ql > qr) return; if(xl == xr && yl == yr) {
for(int i = ql; i <= qr; i++)
chkMin(ans[q[i].id], );
return;
} if(xr - xl > yr - yl) {
int mid = ((xl + xr) >> );
for(int i = yl; i <= yr; i++) {
dij(xl, xr, yl, yr, mid, i);
for(int j = ql; j <= qr; j++) {
int x = id(q[j].xa, q[j].ya), y = id(q[j].xb, q[j].yb);
chkMin(ans[q[j].id], dis[x] + dis[y]);
}
} int l = ql - , r = qr + ;
for(int i = ql; i <= qr; i++) {
if(q[i].xa <= mid && q[i].xb <= mid) tmp[++l] = q[i];
else if(q[i].xa > mid && q[i].xb > mid) tmp[--r] = q[i];
}
for(int i = ql; i <= l; i++) q[i] = tmp[i];
for(int i = r; i <= qr; i++) q[i] = tmp[i]; solve(xl, mid, yl, yr, ql, l);
solve(mid + , xr, yl, yr, r, qr);
} else {
int mid = ((yl + yr) >> );
for(int i = xl; i <= xr; i++) {
dij(xl, xr, yl, yr, i, mid);
for(int j = ql; j <= qr; j++) {
int x = id(q[j].xa, q[j].ya), y = id(q[j].xb, q[j].yb);
chkMin(ans[q[j].id], dis[x] + dis[y]);
}
} int l = ql - , r = qr + ;
for(int i = ql; i <= qr; i++) {
if(q[i].ya <= mid && q[i].yb <= mid) tmp[++l] = q[i];
else if(q[i].ya > mid && q[i].yb > mid) tmp[--r] = q[i];
}
for(int i = ql; i <= l; i++) q[i] = tmp[i];
for(int i = r; i <= qr; i++) q[i] = tmp[i]; solve(xl, xr, yl, mid, ql, l);
solve(xl, xr, mid + , yr, r, qr);
}
} int main() {
// freopen("tourist3.in", "r", stdin);
// freopen("my.out", "w", stdout);
// freopen("Sample.txt", "r", stdin); read(n), read(m); for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++)
verx[id(i, j)] = i, very[id(i, j)] = j; /* for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
printf("%d %d %d\n", id(i, j), verx[id(i, j)], very[id(i, j)]); */ for(int i = ; i <= n; i++)
for(int j = ; j < m; j++) {
int v; read(v);
addEdge(id(i, j), id(i, j + ), v);
}
for(int i = ; i < n; i++)
for(int j = ; j <= m; j++) {
int v; read(v);
addEdge(id(i, j), id(i + , j), v);
} read(qn);
for(int i = ; i <= qn; i++) {
read(q[i].xa), read(q[i].ya), read(q[i].xb), read(q[i].yb);
q[i].id = i;
} memset(ans, 0x3f, sizeof(ans));
solve(, n, , m, , qn); for(int i = ; i <= qn; i++)
printf("%d\n", ans[i]); return ;
}
Luogu 3350 [ZJOI2016]旅行者的更多相关文章
- P3350 [ZJOI2016]旅行者
题目描述 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n*m个路口 (i,j)(1<=i<=n,1&l ...
- 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条从南到北的道路,这些道路两两相交形 ...
- luogu3350 [ZJOI2016]旅行者
链接 P3350 [ZJOI2016]旅行者 题目大意:给出网格图,求两点之间最短路,多组询问. \(n*m\leq10^5\ \ q\leq 10^5\) 考虑\(CDQ\)分治. 首先把询问离线, ...
- Luogu3350 ZJOI2016 旅行者 最短路、分治
传送门 题意:给出一个$N \times M$的网格图,边有边权,$Q$组询问,每组询问$(x_1,y_1)$到$(x_2,y_2)$的最短路.$N \times M \leq 2 \times 10 ...
- ●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 ...
随机推荐
- poj 3128 Leonardo's Notebook——思路(置换)
题目:http://poj.org/problem?id=3128 从环的角度考虑. 原来有奇数个点的环,现在点数不变: 原来有偶数个点的环(设有 k 个点),现在变成两个大小为 k/2 的环. 所以 ...
- Jenkins的用户管理
用户管理入口 Jenkins首页有一个用户,但是只能从那查看用户列表和信息,管理用户的入口在Jenkins->系统管理->管理用户 新建用户 在管理用户左侧有一个新增用户,点击后按照表单填 ...
- (转)Apache转发配置
本文转载自:http://blog.csdn.net/leshjmail/article/details/6163581 安装文件 1.httpd-2.2.15-win32-x86-no_ssl.ms ...
- spring-session之二:简单配置
官方示例:https://docs.spring.io/spring-session/docs/current/reference/html5/#samples 配置Spring Session 在W ...
- Java-Maven-Runoob:Maven 插件
ylbtech-Java-Maven-Runoob:Maven 插件 1.返回顶部 1. Maven 插件 Maven 有以下三个标准的生命周期: clean:项目清理的处理 default(或 bu ...
- PL/SQL 训练01--基础介绍
--开始介绍变量之前,我们先看下怎么在PLSQL写程序,如下我们写了一个块 declare --声明部分,声明变量 v_name ) :='hello world'; begin --执行区域 dbm ...
- DB2的安装
jiangxin@db01:~$ su – root #切换到root用户 密码: root@db01:~# uname -a #查看内核和操作系统信息 Linux db01 4.4.0-66-gen ...
- JavaEE笔记——BaseDao的使用
在Hibernate框架中使用BaseDao主要的作用是减少冗余代码,在对Dao的操作中CRUD可以说是最普通最常见的操作了,基本上面对不同的数据表都会有类似的CRUD操作,BaseDao的思想就是把 ...
- Oracle 11G的间隔(INTERVAL)分区
-- Create table create table MS_BIGTABLE_LOG ( record_date DATE, col_1 VARCHAR2(), col_2 VARCHAR2() ...
- storm和kafka整合
storm和kafka整合 依赖 <dependency> <groupId>org.apache.storm</groupId> <artifactId&g ...