洛谷 P5471 - [NOI2019] 弹跳(二维线段树优化建图+堆优化存边)
一道非常有意思的题(大概可以这么形容?)
首先看到这类一个点想一个区域内连边的题目可以很自然地想到线段树优化建图,只不过这道题是二维的,因此需要使用二维线段树优化建图,具体来说,我们外层开一棵大线段树维护 \(x\) 轴下标区间,大线段树上每个节点又套了个小的动态开点线段树,每次我们从一个点向一个矩形连边时就在动态开点线段树上找到对应的区间并从这个点向这些区间中连边,不难发现这个做法点数是 \(\mathcal O(n\log^2n)\) 级别的,边数是 \(\mathcal O(m\log^2n)\) 级别的,总复杂度 \(m\log^3n\),然鹅梦想很美满,现实很骨感,这个做法,它,MLE 了!因此我们还得考虑别的做法。
这时候就要用到一个叫做”堆优化存边“的 trick 了,在正常的 dijkstra 求最短路的过程中,我们小根堆中存的是起点到每个点的距离与其形成的 pair,但是这次咱们偏不存点,咱们存边,也就是题目中所说的弹跳装置。显然对于一个弹跳装置而言,如果起点到它的出发点 \(p_i\) 的最短路径长度已知,那么它用来更新矩形中所有点的距离就已经知道了——是 \(dis_{p_i}+t_i\),那么我们就将 \(dis_{p_i}+t_i\) 与弹跳装置的编号 \(i\) 看作一个 pair 压入小根堆中,每次取出小根堆的最小节点并找到它对应弹跳装置中的所有节点集合 \(S\)——这个咱们可以用线段树套 set 来求出,然后直接令 \(S\) 当中的点的最短路径为 \(dis_{p_i}+t_i\),然后将这些点直接从线段树中删除,显然每个点最多被访问并删除一次,每个点最多在 \(\log n\) 个节点中出现,再加上 set 的复杂度,总复杂度俩 \(\log\)。而且由于我们每次取出的是贡献最小的弹跳装置,因此每次找出的 \(S\) 中的节点必然是无法被更小的弹跳装置更新的,因此求出来的距离必定是起点到每个点的最短路。这样时间复杂度 \(n\log^2n+m\),空间复杂度 \(n\log n+m\),就不用再担心空间的问题了。
const int MAXN=7e4;
const int MAXM=1.5e5;
int n,m,w,h,dis[MAXN+5];
struct city{
int x,y,id;
city(int _x=0,int _y=0,int _id=0):x(_x),y(_y),id(_id){}
bool operator <(const city &rhs) const{
return (y^rhs.y)?(y<rhs.y):(id<rhs.id);
}
} a[MAXN+5];
priority_queue<pii,vector<pii>,greater<pii> > q;
set<city> st[MAXN*4+5];
vector<int> fr[MAXN+5];
struct bar{int p,l,r,u,d,c;} b[MAXM+5];
void insert(int k,int l,int r,int v){
st[k].insert(a[v]);if(l==r) return;int mid=l+r>>1;
(a[v].x<=mid)?insert(k<<1,l,mid,v):insert(k<<1|1,mid+1,r,v);
}
void del(int k,int l,int r,int v){
st[k].erase(st[k].find(a[v]));if(l==r) return;int mid=l+r>>1;
(a[v].x<=mid)?del(k<<1,l,mid,v):del(k<<1|1,mid+1,r,v);
}
void update(int k,int l,int r,int x,int y){
if(b[x].l<=l&&r<=b[x].r){
while(1){
set<city>::iterator it=st[k].lower_bound(city(0,b[x].d,0));
if(it==st[k].end()||(it->y)>b[x].u) break;
int id=(it->id);dis[id]=y;
for(int t:fr[id]) q.push(mp(y+b[t].c,t));
del(1,1,w,id);
} return;
} int mid=l+r>>1;
if(b[x].r<=mid) update(k<<1,l,mid,x,y);
else if(b[x].l>mid) update(k<<1|1,mid+1,r,x,y);
else update(k<<1,l,mid,x,y),update(k<<1|1,mid+1,r,x,y);
}
int main(){
scanf("%d%d%d%d",&n,&m,&w,&h);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i,insert(1,1,w,i);
for(int i=1;i<=m;i++){
scanf("%d%d%d%d%d%d",&b[i].p,&b[i].c,&b[i].l,&b[i].r,&b[i].d,&b[i].u);
fr[b[i].p].pb(i);
} b[++m].c=0;b[m].l=b[m].r=a[1].x;b[m].u=b[m].d=a[1].y;q.push(mp(0,m));
while(!q.empty()){pii p=q.top();q.pop();/*printf("%d %d\n",p.fi,p.se);*/update(1,1,w,p.se,p.fi);}
for(int i=2;i<=n;i++) printf("%d\n",dis[i]);
return 0;
}
洛谷 P5471 - [NOI2019] 弹跳(二维线段树优化建图+堆优化存边)的更多相关文章
- 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra
题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...
- 洛谷.3437.[POI2006]TET-Tetris 3D(二维线段树)
题目链接 下落一个d*s的方块,则要在这个平面区域找一个最高的h' 更新整个平面区域的值为h+h' 对于本题,维护最大高度h和all 对于平面的x轴维护一棵线段树t1,每个t1的节点维护对应y轴的两棵 ...
- 洛谷P3437 [POI2006]TET-Tetris 3D(二维线段树 标记永久化)
题意 题目链接 Sol 二维线段树空间复杂度是多少啊qwqqq 为啥这题全网空间都是\(n^2\)还有人硬要说是\(nlog^2n\)呀.. 对于这题来说,因为有修改操作,我们需要在外层线段树上也打标 ...
- 洛谷 P3688 - [ZJOI2017]树状数组(二维线段树+标记永久化)
题面传送门 首先学过树状数组的应该都知道,将树状数组方向写反等价于前缀和 \(\to\) 后缀和,因此题目中伪代码的区间求和实质上是 \(sum[l-1...n]-sum[r...n]=sum[l-1 ...
- 洛谷 P3397 地毯 【二维差分标记】
题目背景 此题约为NOIP提高组Day2T1难度. 题目描述 在n*n的格子上有m个地毯. 给出这些地毯的信息,问每个点被多少个地毯覆盖. 输入输出格式 输入格式: 第一行,两个正整数n.m.意义如题 ...
- BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)
题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...
- Codeforces 453E - Little Pony and Lord Tirek(二维线段树+ODT)
Codeforces 题目传送门 & 洛谷题目传送门 一道难度 *3100 的 DS,而且被我自己搞出来了! 不过我终究还是技不如人,因为这是一个 \(n\log^2n\) + 大常数的辣鸡做 ...
- UVA 11297 线段树套线段树(二维线段树)
题目大意: 就是在二维的空间内进行单个的修改,或者进行整块矩形区域的最大最小值查询 二维线段树树,要注意的是第一维上不是叶子形成的第二维线段树和叶子形成的第二维线段树要 不同的处理方式,非叶子形成的 ...
- POJ2155 Matrix二维线段树经典题
题目链接 二维树状数组 #include<iostream> #include<math.h> #include<algorithm> #include<st ...
随机推荐
- Java:并发笔记-03
Java:并发笔记-03 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 3. 共享模型之管程-2 本章内容-2 Monitor wait/notify 3.6 ...
- 鸿蒙轻内核M核的故障管家:Fault异常处理
摘要:本文先简单介绍下Fault异常类型,向量表及其代码,异常处理C语言程序,然后详细分析下异常处理汇编函数实现代码. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列十八 Fault异常处理& ...
- Hdu P1394 Minimum Inversion Number | 权值线段树
题目链接 题目翻译: 约定数字序列a1,a2,...,an的反转数是满足i<j和ai>aj的数对(ai,aj)的数量. 对于给定的数字序列a1,a2,...,an,如果我们将第1到m个数字 ...
- poj 2311 Cutting Game (SG)
题意: 有一张W*H的纸片. 每人每次可以横着撕或者竖着撕,先撕出1*1那一方胜. 数据范围: W and H (2 <= W, H <= 200) 思路: 很好抽象出游戏图的模型,用SG ...
- Java 中 List 分片的 5 种方法!
前些天在实现 MyBatis 批量插入时遇到了一个问题,当批量插入的数据量比较大时,会导致程序执行报错,如下图所示: 原因是 MySQL 只能执行一定长度的 SQL 语句,但当插入的数据量较多时,会生 ...
- es6实现继承详解
ES6中通过class关键字,定义类 class Parent { constructor(name,age){ this.name = name; this.age = age; } speakSo ...
- Linux 兴趣小组2016免试题 第四关揭秘
Linux 兴趣小组2016免试题 点这里 首先贴出第四关链接Linux 兴趣小组2016免试题 第四关 第四关: 进入网址我们看到的是4张扑克牌K,这是什么意思? 要我斗地主?好了,还是乖乖的先查看 ...
- PTA 7-2 邻接表创建无向图 (20分)
PTA 7-2 邻接表创建无向图 (20分) 采用邻接表创建无向图G ,依次输出各顶点的度. 输入格式: 输入第一行中给出2个整数i(0<i≤10),j(j≥0),分别为图G的顶点数和边数. 输 ...
- 开源支持东财自动交易的简单量化交易框架pytrader
pytrader是基于 easytrader 和 easyquotation 的量化交易框架,支持东方财富自动交易,支持进行策略回测. 开源地址:https://github.com/jadepeng ...
- find 删除日志文件
find 命令删除日志文件 find ./my_dir -mtime +10 -type f -delete EXPLANATIONS ./my_dir your directory (replace ...