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]旅行者的更多相关文章

  1. P3350 [ZJOI2016]旅行者

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

  2. bzoj4456: [Zjoi2016]旅行者

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

  3. 4456: [Zjoi2016]旅行者

    4456: [Zjoi2016]旅行者 https://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. 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路

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

  6. luogu3350 [ZJOI2016]旅行者

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

  7. Luogu3350 ZJOI2016 旅行者 最短路、分治

    传送门 题意:给出一个$N \times M$的网格图,边有边权,$Q$组询问,每组询问$(x_1,y_1)$到$(x_2,y_2)$的最短路.$N \times M \leq 2 \times 10 ...

  8. ●BOZJ 4456 [Zjoi2016]旅行者

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

  9. [ZJOI2016]旅行者

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

随机推荐

  1. Django--django-admin.py on windows does not work

    使用命令:Python django-admin.py startproject projectname 使用django-admin.py startapp myblog没有创建新的app,使用下面 ...

  2. C#防止程序多次运行

    经过我的测试,还比较好用,但是有个问题,如果不注销,用另一个用户进入,则程序不能判断出已运行.所以只限于用在单用户环境,还是不太完美. class Program { [STAThread] stat ...

  3. Linux 环境下安装Maven

    1.安装wget命令 如果需要通过使用wget命令,直接通过网络下载maven安装包时,需要在linux系统中安装wget命令. yum -y install wget 2.下载maven安装包 wg ...

  4. redis的安装和类型及基本命令

    一.memcached和redis区别 1. redis 可以存储,memcached用来缓存, 2. 数据类型,memcached只有string:redis有string,链表,哈希结构,集合,有 ...

  5. FIR滤波器和IIR滤波器的区别

    数字滤波器广泛应用于硬件电路设计,在离散系统中尤为常见,一般可以分为FIR滤波器和IIR滤波器,那么他们有什么区别和联系呢. FIR滤波器 定义: FIR滤波器是有限长单位冲激响应滤波器,又称为非递归 ...

  6. contiki学习心路历程【转】xukai871105 大神

    https://blog.csdn.net/xukai871105/article/details/9072993

  7. java从键盘输入打印出直角三角形

    package com.aaa; import java.util.Scanner; //重在参与,欢迎评价,吐槽~~~~//输出直角三角形 public class Se { public stat ...

  8. VirtualBox 虚拟机 centos7 下 设置静态ip 并支持 xshell 远程登陆的设置方法

    1.设置虚拟机使用“桥接模式” 2.使用 vi /etc/sysconfig/network-scripts/ifcfg-enp0s3  打开配置文件(其中 enp0s3 是你的linux的网卡名,在 ...

  9. chrome浏览器手动添加印象笔记剪藏插件

    标签(空格分隔): chrome浏览器,日常办公 一直为每次从网页上复制内容之后,还需要再去复制对应的网址,倍感麻烦.之前偶尔这样操作还可以,最近在学习新东西,要保留下来的网页实在太多,而且不利于分类 ...

  10. php爬虫神器cURL

    cURL 网页资源(编写网页爬虫) 接口资源 ftp服务器文件资源 其他资源 static public function curl($url, $data = array(), $timeout = ...