洛谷 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 ...
随机推荐
- HTTP标签
系统的http状态码知识,我是在<图解http里学习的>. 状态码的职责是告知从服务器端返回的请求结果. 分类如下: 2XX --> 成功 200 OK(一般情况) 204 No C ...
- Java:反射小记
Java:反射小记 对 Java 中的 反射,做一个微不足道的小小小小记 概念 Java 反射指的是在 Java 程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法:对于给定的一个对象, ...
- Scrum Meeting 0501
零.说明 日期:2021-5-1 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 qsy PM&前端 整装待发,准备冲刺 ...
- BZOJ4919[Lydsy1706月赛]大根堆-------------线段树进阶
是不是每做道线段树进阶都要写个题解..根本不会写 Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切 ...
- IdentityServer4 负载均衡配置
在不用到负载之前,一切都很好,但是部署多个实例之后,问题挺多的:session问题.令牌签发后的校验问题. 在此之前,先自查官方文档:Deployment - IdentityServer4 1.0. ...
- Codeforces Round #736 (Div. 2)
A,B,C就不说了,又被D题卡住了..... 感觉怎么说呢,就是题解中的三个提示都已经想到了,就是不知道该怎么解决.... D. Integers Have Friends 简述题意:题目要求你找一个 ...
- Windows7下面手把手教你安装Django - Hongten
我所使用的操作系统是Windows7,内存是2G 在搜索了一些资料发现,对于Django的安装,详细的真的很少,都说的很简化,然而,这篇blog可以手把手教你成功安装Django 对于Django的详 ...
- OpenEuler树莓派基础实验
OpenEuler树莓派基础实验 1.任务详情 1. 参考https://www.cnblogs.com/rocedu/p/14615565.html 完成OpenEuler的安装,提交过程博客和截图 ...
- Loto实践干货(8) 实测 保险丝 用示波器带电流探头
本文用LOTO示波器和5A的电流探头来实验两种常见类型的保险丝的保护曲线.一种是熔断型的,另一种是自恢复型的.我们通常需要在一些电路中对电流过大的情况做保护,比如防止用户把输出源短路,比如防止用户对电 ...
- 变量命名网站 Codelf
程序员最头疼的事情除了头发以外就是给变量或函数命名,一开始学编程语言的时候还可以 abc.a1.x2 等方式命名,等到工作过程中开始真正的项目开发时,如果还是这样随意的命名,即使同事可以忍受你的 ab ...