【BZOJ 4456】【UOJ #184】【ZJOI 2016】旅行者
http://www.lydsy.com/JudgeOnline/problem.php?id=4456
参考(抄)的晨爷的题解(代码)
对矩形进行分治。
每次对一个分治中的矩形,枚举中轴线上的点,依次做dijkstra,范围是该矩形内的点。
处理出中轴线上的点到矩形内所有点的最短路,这样,两点在该矩形内的询问就可以用$dist+dist$更新了,意义是两点经过该中轴线的最短路。
在把矩形劈成两半,把询问也分成两半,递归分治。
因为两点间的最短路一定会穿过其中一个分治矩形的中轴线,所以这么做是正确的。
时间复杂度是$O(n\sqrt{n}log^2n)$,不理解少一个$log$的复杂度的做法。
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 20003;
const int Qnum = 500003;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = (k << 3) + (k << 1) + c - '0';
return k * fh;
} bool inq[N];
struct node {int nxt, to, w;} E[N << 2];
struct query {int x0, y0, x1, y1, id;} Q[Qnum], sta[Qnum];
int q, tot = 0, cnt = 0, point[N], n, m, ans[Qnum], dist[N]; void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;}
int get(int x, int y) {return (x - 1) * m + y;} struct Point {
int id, dist;
Point(int _id = 0, int _dist = 0) : id(_id), dist(_dist) {}
bool operator < (const Point &A) const {
return dist > A.dist;
}
};
priority_queue <Point> qu;
void dijkstra(int S, int x0, int y0, int x1, int y1) {
int u;
for(int i = x0; i <= x1; ++i)
for(int j = y0; j <= y1; ++j) {
u = get(i, j);
dist[u] = 0x7fffffff; inq[u] = false;
}
dist[S] = 0;
Point x;
qu.push(Point(S, 0));
while (!qu.empty()) {
x = qu.top();
qu.pop();
if (inq[x.id]) continue;
inq[x.id] = true;
for(int i = point[x.id]; i; i = E[i].nxt)
if (x.dist + E[i].w < dist[E[i].to]) {
dist[E[i].to] = x.dist + E[i].w;
qu.push(Point(E[i].to, dist[E[i].to]));
}
}
} void cdq(int x0, int y0, int x1, int y1, int Ql, int Qr) {
if (Ql > Qr) return;
if (x1 - x0 > y1 - y0) {
int mid = (x1 + x0) >> 1, po, tmp_l, tmp_r;
for(int i = y0; i <= y1; ++i) {
po = get(mid, i);
dijkstra(po, x0, y0, x1, y1);
for(int j = Ql; j <= Qr; ++j)
ans[Q[j].id] = min(ans[Q[j].id], dist[get(Q[j].x0, Q[j].y0)] + dist[get(Q[j].x1, Q[j].y1)]);
} tmp_l = Ql - 1; tmp_r = Qr + 1;
for(int i = Ql; i <= Qr; ++i)
if (Q[i].x0 < mid && Q[i].x1 < mid) sta[++tmp_l] = Q[i];
else if (Q[i].x0 > mid && Q[i].x1 > mid) sta[--tmp_r] = Q[i];
for(int i = Ql; i <= tmp_l; ++i) Q[i] = sta[i];
for(int i = tmp_r; i <= Qr; ++i) Q[i] = sta[i]; cdq(x0, y0, mid - 1, y1, Ql, tmp_l);
cdq(mid + 1, y0, x1, y1, tmp_r, Qr);
} else {
int mid = (y0 + y1) >> 1, po, tmp_l, tmp_r;
for(int i = x0; i <= x1; ++i) {
po = get(i, mid);
dijkstra(po, x0, y0, x1, y1);
for(int j = Ql; j <= Qr; ++j)
ans[Q[j].id] = min(ans[Q[j].id], dist[get(Q[j].x0, Q[j].y0)] + dist[get(Q[j].x1, Q[j].y1)]);
} tmp_l = Ql - 1; tmp_r = Qr + 1;
for(int i = Ql; i <= Qr; ++i)
if (Q[i].y0 < mid && Q[i].y1 < mid) sta[++tmp_l] = Q[i];
else if (Q[i].y0 > mid && Q[i].y1 > mid) sta[--tmp_r] = Q[i];
for(int i = Ql; i <= tmp_l; ++i) Q[i] = sta[i];
for(int i = tmp_r; i <= Qr; ++i) Q[i] = sta[i]; cdq(x0, y0, x1, mid - 1, Ql, tmp_l);
cdq(x0, mid + 1, x1, y1, tmp_r, Qr);
}
} int main() {
n = in(); m = in();
int len, Point;
for(int i = 1; i <= n; ++i)
for(int j = 1; j < m; ++j) {
len = in();
Point = get(i, j);
ins(Point, Point + 1, len);
ins(Point + 1, Point, len);
}
for(int i = 1; i < n; ++i)
for(int j = 1; j <= m; ++j) {
len = in();
Point = get(i, j);
ins(Point, Point + m, len);
ins(Point + m, Point, len);
} q = in();
int x0, y0, x1, y1;
memset(ans, 127, sizeof(int) * (q + 1));
for(int i = 1; i <= q; ++i) {
x0 = in(); y0 = in(); x1 = in(); y1 = in();
if (x0 == x1 && y0 == y1) {ans[i] = 0; continue;}
Q[++tot] = (query) {x0, y0, x1, y1, i};
} memset(inq, 1, sizeof(bool) * (n * m + 3));
cdq(1, 1, n, m, 1, tot); for(int i = 1; i <= q; ++i) printf("%d\n", ans[i]);
return 0;
}
终于AC了
【BZOJ 4456】【UOJ #184】【ZJOI 2016】旅行者的更多相关文章
- [BZOJ 4573][ZJOI 2016]大森林
[LOJ 2092][BZOJ 4573][UOJ 195][ZJOI 2016]大森林 题意 给定一个树序列, 初始时所有树都只有一个点, 要求支持三种操作: 区间种树(在某个特定点上长出一个子结点 ...
- [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)
[BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...
- BZOJ4456/UOJ#184[Zjoi2016]旅行者 分治 最短路
原文链接http://www.cnblogs.com/zhouzhendong/p/8682133.html 题目传送门 - BZOJ4456 题目传送门 - UOJ#184 题意 $n\times ...
- [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字
[LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字 题意 给定一个大串 \(S\) 以及 \(q\) 次询问, 每次询问给定一个串 \(T\) 和区间 \([l, ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- 【BZOJ 4455】【UOJ #185】【ZJOI 2016】小星星
http://www.lydsy.com/JudgeOnline/problem.php?id=4455 http://uoj.ac/problem/185 有一个$O(n^n)$的暴力,放宽限制可以 ...
- BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...
- 【ZJOI 2016】旅行者
题意 http://uoj.ac/problem/184 题解 大概是神题. 网格图上跑最短路有一个经典的优化方式:分治分组跑最短路. 对于这道题,设矩形长为 \(n\),宽为 \(m\),则对 \( ...
- bzoj 4456 [Zjoi2016]旅行者
题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 题解 分治 设当前work的区间为(x1,y1,x2,y2) 我们将长边分成两半 不妨 ...
随机推荐
- 给深度学习入门者的Python快速教程 - numpy和Matplotlib篇
始终无法有效把word排版好的粘贴过来,排版更佳版本请见知乎文章: https://zhuanlan.zhihu.com/p/24309547 实在搞不定博客园的排版,排版更佳的版本在: 给深度学习入 ...
- Spring AOP 5种通知与java动态代理
接口,要求为每个方法前后添加日志 @Component("arithmeticCalculator") public class ArithmeticCalculatorImpl ...
- inverse理解
首先术语inverse 被翻译为反转的意思.inverse 制定了关联关系中的方向. 当set的inverse属性默认情况下,hibernate会按照持久化对象的属性变化来同步更新数据库. 得到两条s ...
- SQL触发器、事物
触发器: 触发器为特殊类型的存储过程,可在执行语言事件时自动生效.SQL Server 包括三种常规类型的触发器:DML 触发器.DDL 触发器和登录触发器. 当服务器或数据库中发生数据定义语言 (D ...
- tomocat设置首次访问时的页面
怎么设置Tomcat服务器的默认首页(欢迎页) 一般做Java web开发,有时候会选择Tomcat用作服务器,我在本机开发测试用的也是Tomcat,现在有一个问题是,我们都知道当访问一个网站的时候, ...
- SVN的使用方法
SVN的使用方法: 新建文件夹:文件夹1 在文件夹上点击右键--选择 SVN Checkout--弹出checkout窗口 下载文件的url获取:打开SVN--在要下载的文件上点击右键--点击Copy ...
- 那些年我们用到的jquery选择器!!
一:基本选择器 1:标签选择器: 返回值(元素集合):$("h2")选取所有h2元素. 2:类选择器:返回值(元素集合):$(".title")选取所有clas ...
- 个人PHP开发环境的选择与搭建
入职一个多月,重新调整了一下自己电脑的开发环境,现在写出来,算是作为自己的笔记. 如果你是该文章的读者,请忍受文章内的所有小章节都没有具体的步骤. 因为平时还要打游戏(划掉),所以电脑系统一直是Win ...
- PAT 1002. 写出这个数 (20)
读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值.这里保证n小于10100. 输出格式:在一行内输出n的各位数字之和的每 ...
- Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
概要 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解Arra ...