题目传送门:LOJ #3159

题意简述:

二维平面上有 \(n\) 个整点,给定每个整点的坐标 \((x_i,y_i)\)。

有 \(m\) 种边,第 \(i\) 种边从 \(p_i\) 号点连向满足 \(l_i\le x_j\le r_i\) 和 \(d_i\le y_j\le u_i\) 的点 \(j\),即一个矩形范围内的所有点。

求 \(1\) 号点到其它每个点的最短路长度。

题解:

考虑 Dijkstra 算法求最短路的过程:

一开始只有起点的距离为 \(0\),而其它点距离为无限大。

每次取出一个距离最短的没被更新过的点,用它更新它能到达的所有未被更新过的点的距离,并将其标记为已被更新。

重复这个过程直到所有点均被更新。

上述过程一般使用单调队列来维护距离最短的点。

而在此题中,一次更新时可能加入的点会有很多很多,不能每次将其一并加入。

可以考虑加入一条边而非点,加入的这条边就代表了这条边连向的所有点的距离。

类似地,每次取出距离最短的边,此时这条边代表的矩形内部的所有点均可以进行更新,因为只会去更新未被更新过的点,所以更新完这些点的距离后,可以把这些点全部删除。

上述方法是最短路中包含“一对多”,“多对多”的边时的处理办法。还有一种方法是使用数据结构模型优化建边,但是一般不会比这种方法来得优。

至于具体如何维护矩形删点操作,删点时可以暴力一个个删除,因为每个点只会被删除一次,问题在于如何快速找到要删除的点。

这里我使用线段树套平衡树(std::set)维护,外层线段树处理横坐标上的区间,内层平衡树可以快速访问目标点将其删除。

下面是代码,时间复杂度为 \(\mathcal{O}(n\log^2n+m\log m)\):

#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <set> #define mp std::make_pair
typedef std::pair<int, int> pii;
typedef std::multiset<pii>::iterator iter;
const int MN = 70005, MM = 150005;
const int MS = 1 << 18 | 7; int N, M, W, H, yp[MN], vis[MN], dis[MN];
int h[MN], nxt[MM], et[MM], eL[MM], eR[MM], eD[MM], eU[MM];
std::multiset<pii> st[MS];
std::priority_queue<pii> pq;
void Ins(int i, int l, int r, int x, int id) {
st[i].insert(mp(yp[id], id));
if (l == r) return ;
int mid = (l + r) >> 1;
if (x <= mid) Ins(i << 1, l, mid, x, id);
else Ins(i << 1 | 1, mid + 1, r, x, id);
}
void Del(int i, int l, int r, int id, int d) {
if (r < eL[id] || eR[id] < l) return ;
if (eL[id] <= l && r <= eR[id]) {
iter it = st[i].lower_bound(mp(eD[id], 0)), tmp;
while (it != st[i].end() && it -> first <= eU[id]) {
int u = it -> second;
if (!vis[u]) {
vis[u] = 1, dis[u] = d;
for (int j = h[u]; j; j = nxt[j])
pq.push(mp(-d - et[j], j));
}
tmp = it, ++it, st[i].erase(tmp);
}
return ;
}
int mid = (l + r) >> 1;
Del(i << 1, l, mid, id, d);
Del(i << 1 | 1, mid + 1, r, id, d);
} int main() {
freopen("jump.in", "r", stdin);
freopen("jump.out", "w", stdout);
scanf("%d%d%d%d", &N, &M, &W, &H);
for (int i = 1, x; i <= N; ++i) {
scanf("%d%d", &x, &yp[i]);
Ins(1, 1, W, x, i);
}
for (int i = 1, p; i <= M; ++i) {
scanf("%d%d%d%d%d%d", &p, &et[i], &eL[i], &eR[i], &eD[i], &eU[i]);
nxt[i] = h[p], h[p] = i;
}
dis[1] = 0, vis[1] = 1;
for (int i = h[1]; i; i = nxt[i])
pq.push(mp(-et[i], i));
while (!pq.empty()) {
pii ed = pq.top(); pq.pop();
int dis = -ed.first, id = ed.second;
Del(1, 1, W, id, dis);
}
for (int i = 2; i <= N; ++i) printf("%d\n", dis[i]);
return 0;
}

LOJ 3159: 「NOI2019」弹跳的更多相关文章

  1. LOJ 3158: 「NOI2019」序列

    题目传送门:LOJ #3158. 题意简述: 给定两个长度为 \(n\) 的正整数序列 \(a,b\),要求在每个序列中都选中 \(K\) 个下标,并且要保证同时在两个序列中都被选中的下标至少有 \( ...

  2. LOJ 3160: 「NOI2019」斗主地

    题目传送门:LOJ #3160. 简要题意: 有一个长度为 \(n\) 的序列 \(a\),初始时 \(a_i=i\) 或 \(a_i=i^2\),这取决于 \(\mathrm{type}\) 的值. ...

  3. LOJ 3156: 「NOI2019」回家路线

    题目传送门:LOJ #3156. 题意简述: 有一张 \(n\) 个点 \(m\) 条边的有向图,边有两个权值 \(p_i\) 和 \(q_i\)(\(p_i<q_i\))表示若 \(p_i\) ...

  4. 「NOI2019」弹跳(KD树)

    题意:w×h网格中有n个点,m条边.每条边可以从p点花费t时间到一个矩形中的任意点,求1号点到每个点的最少时间. \(1<=w,h<=n<=70000,1<=m<=150 ...

  5. @loj - 3157@「NOI2019」机器人

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 R 喜欢研究机器人. 最近,小 R 新研制出了两种机器人,分 ...

  6. loj3161「NOI2019」I 君的探险(随机化,整体二分)

    loj3161「NOI2019」I 君的探险(随机化,整体二分) loj Luogu 题解时间 对于 $ N \le 500 $ 的点,毫无疑问可以直接 $ O(n^2) $ 暴力询问解决. 考虑看起 ...

  7. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  8. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  9. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

随机推荐

  1. VSCode编写C/C++语言,配置文件和注意事项

    前言 主要是自己先下载好VSCode,然后在自己电脑上安装好就行了,但是VSCode是编辑器,不是IDE,所以需要自己配置文件,主要有四个都是以.json结尾的文件,这里默认已经装过C/C++的编辑器 ...

  2. [LeetCode] 907. Sum of Subarray Minimums 子数组最小值之和

    Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...

  3. [LeetCode] 34. Find First and Last Position of Element in Sorted Array 在有序数组中查找元素的第一个和最后一个位置

    Given an array of integers nums sorted in ascending order, find the starting and ending position of ...

  4. IDEA 部署Tomcat教程(透彻理解操作)

    目录 首先我们看一下 IDEA 里的当前项目结构配置 设置 Web 资源目录和 Tomcat读取的 web.xml 配置文件 Tomcat 的 Run/Debug 配置 处理常见问题 Web资源找不到 ...

  5. Loj #2529. 「ZJOI2018」胖

    Loj #2529. 「ZJOI2018」胖 题目描述 Cedyks 是九条可怜的好朋友(可能这场比赛公开以后就不是了),也是这题的主人公. Cedyks 是一个富有的男孩子.他住在著名的 The P ...

  6. luogu P2495 [SDOI2011]消耗战 |虚树+LCA+dp

    题目描述 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知 ...

  7. Spring Boot入门及第一个案例

    一:SpringBoot是什么 springboot是对spring的缺点进行改善和优化,约定大于配置  开箱即用  没有代码生成 也无需xml 文件配置   可以修改属性值来满足需求 1) Spri ...

  8. 线程池 ThreadPoolExecutor 类的源码解析

    线程池 ThreadPoolExecutor 类的源码解析: 1:数据结构的分析: private final BlockingQueue<Runnable> workQueue;  // ...

  9. OCC与MVCC 的区别

    一.前言 在数据库中,并发控制是指在多个用户/进程/线程同时对数据库进行操作时,如何保证事务的一致性和隔离性的,同时最大程度地并发. 当多个用户/进程/线程同时对数据库进行操作时,会出现3种冲突情形: ...

  10. struts2的使用入门

    虽然说Struts2现在已经被SpringMVC框架淘汰了,据说是有很多安全漏洞.但是Struts2作为一个成熟的MVC框架,还是有必要了解一下的,好歹是曾经风光一时的前辈,老祖宗的东西不能丢下,里面 ...