[NOI2019] 弹跳
题意:
给你平面上的$n$个点,共有$m$个弹跳装置。
每个弹跳装置可以从点$p_{i}$以$t_{i}$的代价跳到矩形$(L_{i},D_{i}),(R_{i},U_{i})$中的任何一个点。
现在请你对于每座城市求出从1号点跳到它的最小代价。
$n\leq 70000,m\leq 150000$。
题解:不把边建出来的$KD-tree$优化建图。
看一眼就知道$KD-tree$优化建图,但如果把所有边都建出来就爆炸了。
设原图上的点是实点,$KD-tree$上的点(代表一个实点和一个矩形)是虚点。
那么在$Dijkstra$到每个点的时候:
- 若是实点,在$KD-tree$上查找能连的虚点/实点并向其连带权边。
- 若是虚点,向它的两个儿子和它对应的实点连权为0的边。
时间复杂度$O(m\sqrt{n})$,空间复杂度$O(m\sqrt{n})$(实际上只有优先队列可能达到这个空间,其他都是$O(n)$)。
没了。不知道为什么有人写线段树。
代码:
#include<bits/stdc++.h>
#define maxn 200005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long
#define rint register int
#define debug(x) cerr<<#x<<": "<<x<<endl
#define fgx cerr<<"--------------"<<endl
#define dgx cerr<<"=============="<<endl using namespace std;
struct Point{int x[],iid;}p[maxn];
int mx[maxn][],mn[maxn][],id[maxn],ls[maxn],rs[maxn];
int tot,np,dis[maxn<<],vis[maxn<<],tim[maxn];
int L[maxn],R[maxn],D[maxn],U[maxn];
struct node{int u,d;bool operator<(const node &b)const{return d>b.d;}};
priority_queue<node> q; vector<int> vc[maxn]; inline int read(){
int x=,f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
} inline node md(int u,int d){node res;res.u=u,res.d=d;return res;}
inline void upd(int u,int v){if(dis[u]>v){dis[u]=v,q.push(md(u,v));}}
inline bool ok(int xa,int ya,int xb,int yb){return xb<=xa&&ya<=yb;}
inline bool cmp(Point a,Point b){return (!np)?(a.x[]<b.x[]):(a.x[]<b.x[]);}
inline void pushup(int k){
for(rint i=;i<;i++){
mx[k][i]=mn[k][i]=p[id[k]].x[i];
if(ls[k]) mx[k][i]=max(mx[k][i],mx[ls[k]][i]),mn[k][i]=min(mn[k][i],mn[ls[k]][i]);
if(rs[k]) mx[k][i]=max(mx[k][i],mx[rs[k]][i]),mn[k][i]=min(mn[k][i],mn[rs[k]][i]);
}
}
inline int build(int l,int r,int type){
if(l>r) return ;
int mid=l+r>>,k=++tot;
id[k]=mid,np=type;
nth_element(p+l,p+mid,p+r+,cmp);
ls[k]=build(l,mid-,type^);
rs[k]=build(mid+,r,type^);
pushup(k); return k;
}
inline void add(int l,int r,int d,int u,int c,int k){
if(mx[k][]<l || mn[k][]>r || mx[k][]<d || mn[k][]>u) return;
if(ok(mn[k][],mx[k][],l,r)&&ok(mn[k][],mx[k][],d,u)){upd(k,c);return;}
if(ok(p[id[k]].x[],p[id[k]].x[],l,r)&&ok(p[id[k]].x[],p[id[k]].x[],d,u)) upd(p[id[k]].iid,c);
if(ls[k]) add(l,r,d,u,c,ls[k]); if(rs[k]) add(l,r,d,u,c,rs[k]);
} inline void Dijkstra(int s,int n){
memset(vis,,sizeof(vis));
memset(dis,,sizeof(dis));
dis[s]=,q.push(md(s,));
while(!q.empty()){
rint u=q.top().u; q.pop();
if(vis[u]) continue; vis[u]=;
if(u<=n) for(rint i=;i<vc[u].size();i++)
add(L[vc[u][i]],R[vc[u][i]],D[vc[u][i]],U[vc[u][i]],dis[u]+tim[vc[u][i]],n+);
else upd(p[id[u]].iid,dis[u]),upd(ls[u],dis[u]),upd(rs[u],dis[u]);
}
} int main(){
freopen("jump.in","r",stdin);
freopen("jump.out","w",stdout);
int n=read(),m=read(),w=read(),h=read();
for(rint i=;i<=n;i++)
p[i].x[]=read(),p[i].x[]=read(),p[i].iid=i;
tot=n,build(,n,);
for(rint i=;i<=m;i++){
int p=read();tim[i]=read();
L[i]=read(),R[i]=read();
D[i]=read(),U[i]=read();
vc[p].push_back(i);
}
Dijkstra(,n);
for(rint i=;i<=n;i++) printf("%d\n",dis[i]);
return ;
}
D2T1
[NOI2019] 弹跳的更多相关文章
- 【题解】Luogu P5471 [NOI2019]弹跳
原题传送门 先考虑部分分做法: subtask1: 暴力\(O(nm)\)枚举,跑最短路 subtask2: 吧一行的点压到vector中并排序,二分查找每一个弹跳装置珂以到达的城市,跑最短路 sub ...
- 洛谷 P5471 - [NOI2019] 弹跳(二维线段树优化建图+堆优化存边)
题面传送门 一道非常有意思的题(大概可以这么形容?) 首先看到这类一个点想一个区域内连边的题目可以很自然地想到线段树优化建图,只不过这道题是二维的,因此需要使用二维线段树优化建图,具体来说,我们外层开 ...
- [NOI2019]弹跳(KD-Tree/四分树/线段树套平衡树 优化建图+Dijkstra)
本题可以用的方法很多,除去以下三种我所知道的就还有至少三种. 方法一:类似线段树优化建图,将一个平面等分成四份(若只有一行或一列则等分成两份),然后跑Dijkstra即可.建树是$O(n\log n) ...
- luogu P5471 [NOI2019]弹跳
luogu 因为是一个点向矩形区域连边,所以可以二维数据结构优化连边,但是会MLE.关于维护矩形的数据结构还有\(KD-Tree\),所以考虑\(KDT\)优化连边,空间复杂度\(m\sqrt n\) ...
- luogu 5471 [NOI2019]弹跳 KDtree + Dijkstra
题目链接 第一眼就是 $KDtree$ 优化建图然而,空间只有 $128mb$,开不下 时间不吃紧,考虑直接跑 $Dijkstra$ $Dijkstra$ 中存储的是起点到每个输入时给出的矩阵的最 ...
- p5471 [NOI2019]弹跳
分析 代码 #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define ...
- [NOI2019]弹跳(KD-Tree)
被jump送退役了,很生气. 不过切了这题也进不了队,行吧. 退役后写了一下,看到二维平面应该就是KD树,然后可以在KD树上做最短路,然后建立堆和KDTree.然后每次更新则是直接把最短路上的节点删掉 ...
- 题解 [NOI2019]弹跳
题目传送门 题目大意 给出 \(n\) 做城市,每座城市都有横纵坐标 \(x,y\).现在给出 \(m\) 个限制 \(p,t,l,r,d,u\),表示从 \(p\) 城市出发,可以花费 \(t\) ...
- 【NOI2019】弹跳(KDT优化建图)
Description 平面上有 \(n\) 个点,分布在 \(w \times h\) 的网格上.有 \(m\) 个弹跳装置,由一个六元组描述.第 \(i\) 个装置有参数:\((p_i, t_i, ...
随机推荐
- ** PC端完美兼容各种分辨率的简便方法 **
原文链接:https://blog.csdn.net/qq_43156398/article/details/102785370 PS:此方法需使用到less或者scss的@变量来支持 以设计图 19 ...
- ANDROID培训准备资料之项目结构简单介绍
Android Studio项目结构初步主要介绍下面几个文件夹,后续再补充 (1)java文件夹的介绍 (2)Res文件夹的介绍 (3)R文件的介绍 (4)Manifests文件夹的介绍 我们先看看整 ...
- [b0009] 玩Hadoop中碰到的各种错误
1. Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class mp.filetest.WordCount2 ...
- vue定时器+弹框 跳到登陆页面
1.做一个请求拦截,并弹框提示几秒后,跳转到登陆首页或是点击确定之后直接跳转拦截用了this.$axios.interceptors.response页面上的弹框组件用了vux的组件vux地址:htt ...
- centos7 yum 安装lnmp
centos7 yum 安装lnmp 安装7.2把7.1改成7.2就行 使用第三方扩展epel源安装php7.2 #移除旧版php [root@web02 ~]# yum remove php-m ...
- Shel脚本-初步入门之《01》
Shel脚本-初步入门-什么是 Shell 1.什么是 Shell Shell 是一个命令解释器,它的作用是解释执行用户输入的命令及程序等.Shell 存在于操作系统的最外层,负责与用户直接对话,把用 ...
- FFMPEG+SDL实现视频播放器
一. 前言 基于学习ffmpeg和sdl,写一个视频播放器是个不错的练手项目. 视频播放器的原理很多人的博客都有讲过,这里出于自己总结的目的,还是会做一些概况. 二. 视频播放器基本原理 2.1 解封 ...
- eclipse配置JDK和设置编译版本的几种方法
eclipse配置JDK和设置编译版本的几种方法 2016-12-13 16:08 http://blog.csdn.net/gnail_oug/article/detail ...
- luoguP2260 [清华集训2012]模积和
题意 \(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}n\%i*m\%j*[i!=j]\) \(\sum\limits_{i=1}^{n}\sum\limits ...
- 缓存原理,自己写一个缓存类(c#版)
.net中的MemoryCache是通过内部封装一个静态Dictionary 自己写一个缓存,来看看内部怎么实现的 public class CustomerCache : ICache { priv ...