P5471- K-D tree优化建图-弹跳

优化建图是一种思想。

题意

有\(n\)个城市分布在小鸟岛上,有\(m\)个弹弓分布在这些城市里。因为弹弓体积大,固定麻烦,所以每个弹弓只能把小鸟弹飞到一块固定的矩形范围内的城市,同时小鸟会在空中滞留\(t_i\)的时间。闪电黄的家在1号城市,追求速度的它想知道,若只使用弹弓出行,它从家到其他所有城市的最短时间花费是多少。

抱歉魔改了题面,但是这个题意真的太像愤怒的小鸟了好吗

思路

暴力:枚举每两个城市间是否能转移进行建图跑最短路。

太浪费了,这么大的矩形有很多点肯定连不上的呀。根据套路,我们想个数据结构优化建图。

  • 二维线段树优化建图
  • 树套树优化建图
  • K-D tree优化建图

前两个我不会

首先我们把这n个城市建成2-D tree,然后跑Dijkstra:

若当前结点位置在转移的范围内,插入队列,递归查找子节点并更新覆盖范围。

若弹跳的范围与树上结点覆盖的范围有交,查找之,否则不查找。

就这么简单。怎么说K-D tree就是优雅的暴力呢。

实现

我们用一个结构体node存储树上节点信息,用一个结构体data表示一个转移(边)。

对于一个转移,每次从根开始查找,根据以上策略遍历整棵树。时间复杂度O(能过)。事实上,我还跑了目前luogu榜一(醒醒啊你只是因为评测机最近变快了)

把查找单独拉出来:

inline bool cross(node a,data b){return a.l[0]<=b.r[0] and a.r[0]>=b.l[0] and a.l[1]<=b.r[1] and a.r[1]>=b.l[1];}
void solve(node& x,data& p){
if(!x.del and x.in(p)){//若该点坐标在覆盖范围内
if(x.id!=1){
dis[x.id]=p.v;
for(int i=head[x.id];i;i=nxt[i]){//遍历所有能到的位置
data u=to[i];
u.v+=p.v;
q.push(u);
}
}
x.del=1;//根据dijkstra的贪心策略,该点不再入队
x.clear();//为了保留结点查询的作用。下面会更新范围
}
if(x.son[0]){
node &now=e[x.son[0]];
if(cross(now,p)) solve(now,p);//注意这里判断的是矩形是否有交而非城市坐标
if(x.del) x.copy(now);
else x.update(now);//更新范围
}
if(x.son[1]){
node &now=e[x.son[1]];
if(cross(now,p)) solve(now,p);
if(x.del and !x.son[0]) x.copy(now);
else x.update(now);//更新范围
}
}

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=7e4+10,maxm=15e4,INF=0x3f3f3f3f;
int n,m,w,h,root,dis[maxn];
struct data{
int v,l[2],r[2];
inline bool operator < (const data &zp) const{return v>zp.v;}
};
int ecnt,head[maxm],nxt[maxm];
data to[maxm];
inline void add(int a,data b){
to[++ecnt]=b,nxt[ecnt]=head[a],head[a]=ecnt;
}
struct node{
int x[2],l[2],r[2],son[2],id;
static int d;//“只是声明我要用这个变量,但是它现在还不存在”
bool del;
inline void clear(){
for(int i=0;i<2;i++) x[i]=0,l[i]=INF,r[i]=-INF;
}
inline void init(int zp){
for(int i=0;i<2;i++) x[i]=l[i]=r[i]=read();
id=zp;
}
inline void update(const node &zp){
for(int i=0;i<2;i++) l[i]=min(l[i],zp.l[i]),r[i]=max(r[i],zp.r[i]);
}
inline void copy(const node &zp){
for(int i=0;i<2;i++) l[i]=zp.l[i],r[i]=zp.r[i];
}
inline bool operator < (const node &zp) const{return x[d]<zp.x[d];};
inline bool in(const data &zp) const {return x[0]>=zp.l[0] and x[0]<=zp.r[0] and x[1]>=zp.l[1] and x[1]<=zp.r[1];}
}e[maxn];
int node::d;//现在这个变量存在了,并且每个node都会用它
int build(int l,int r,int d){
node::d=d;
int mid=l+r>>1;
nth_element(e+l,e+mid,e+r+1);
if(l<mid) e[mid].update(e[e[mid].son[0]=build(l,mid-1,d^1)]);
if(r>mid) e[mid].update(e[e[mid].son[1]=build(mid+1,r,d^1)]);
return mid;
}
priority_queue<data> q;
inline bool cross(node a,data b){return a.l[0]<=b.r[0] and a.r[0]>=b.l[0] and a.l[1]<=b.r[1] and a.r[1]>=b.l[1];}
void solve(node& x,data& p){
if(!x.del and x.in(p)){
if(x.id!=1){
dis[x.id]=p.v;
for(int i=head[x.id];i;i=nxt[i]){
data u=to[i];
u.v+=p.v;
q.push(u);
}
}
x.del=1;
x.clear();
}
if(x.son[0]){
node &now=e[x.son[0]];
if(cross(now,p)) solve(now,p);
if(x.del) x.copy(now);
else x.update(now);
}
if(x.son[1]){
node &now=e[x.son[1]];
if(cross(now,p)) solve(now,p);
if(x.del and !x.son[0]) x.copy(now);
else x.update(now);
}
}
inline void work(){
n=read(),m=read(),w=read(),h=read();
for(int i=1;i<=n;i++) e[i].init(i);
root=build(1,n,0);
memset(dis,INF,sizeof dis);
dis[1]=0;
for(int i=1;i<=m;i++){
data zp;
int x=read();
zp.v=read(),zp.l[0]=read(),zp.r[0]=read(),zp.l[1]=read(),zp.r[1]=read();
add(x,zp);
}
for(int i=head[1];i;i=nxt[i]) q.push(to[i]);
while(!q.empty()){
data x=q.top();q.pop();
solve(e[root],x);
}
for(int i=2;i<=n;i++) printf("%d\n",dis[i]);
}
}
signed main(){
star::work();
return 0;
}

PS:据银牌学姐推荐,方差建树常数大,K维循环建树虽然有时候会被卡但实际可能比前者优秀。

为啥题面那么喜欢跳蚤用小鸟们不可爱吗owo

自己吃别人嚼过的馒头为啥还敢写题解?因为觉得自己的马蜂太好看了所以来分享一下

P5471- K-D tree优化建图-弹跳的更多相关文章

  1. 【NOI2019】弹跳(KDT优化建图)

    Description 平面上有 \(n\) 个点,分布在 \(w \times h\) 的网格上.有 \(m\) 个弹跳装置,由一个六元组描述.第 \(i\) 个装置有参数:\((p_i, t_i, ...

  2. [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)

    [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...

  3. 洛谷3783 SDOI2017 天才黑客(最短路+虚树+边转点+线段树优化建图)

    成功又一次自闭了 怕不是猪国杀之后最自闭的一次 一看到最短路径. 我们就能推测这应该是个最短路题 现在考虑怎么建图 根据题目的意思,我们可以发现,在本题中,边与边之间存在一些转换关系,但是点与点之间并 ...

  4. [SDOI2017]天才黑客[最短路、前缀优化建图]

    题意 一个 \(n\) 点 \(m\) 边的有向图,还有一棵 \(k\) 个节点的 trie ,每条边上有一个字符串,可以用 trie 的根到某个节点的路径来表示.每经过一条边,当前携带的字符串就会变 ...

  5. 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流

    [BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...

  6. 洛谷P3783 [SDOI2017]天才黑客(前后缀优化建图+虚树+最短路)

    题面 传送门 题解 去看\(shadowice\)巨巨写得前后缀优化建图吧 话说我似乎连线段树优化建图的做法都不会 //minamoto #include<bits/stdc++.h> # ...

  7. 【ARC069F】Flags 2-sat+线段树优化建图+二分

    Description ​ 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input ​ 第一行一个整数 N. ​ 接下来 N 行每行两个整数 xi, ...

  8. 【bzoj4699】树上的最短路(树剖+线段树优化建图)

    题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...

  9. 【bzoj4383】[POI2015]Pustynia 线段树优化建图+差分约束系统+拓扑排序

    题目描述 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r- ...

随机推荐

  1. C# 强行锁定 第三方 外部 应用程序窗体窗口的分辨率尺寸大小 禁止鼠标拖拽改变窗口大小

    我们也许会有一些奇怪的需求,比如说禁止一个外部程序的窗口大小更改. 如果我们没法修改外部程序的代码,那要怎么做呢? 当然,我们可以通过DLL注入目标程序的方式去Hook或registry一个事件来检测 ...

  2. 对标 Spring Boot & Cloud ,轻量框架 Solon 1.4.14 发布

    Solon 是一个轻量的Java基础开发框架.强调,克制 + 简洁 + 开放的原则:力求,更小.更快.更自由的体验.支持:RPC.REST API.MVC.Job.Micro service.WebS ...

  3. 「题解」USACO15FEB Fencing the Herd G

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书: 题目 题目链接:洛谷 P3122.USACO 官网. 题意概述 给你平面上的一些点和直线,有两种操作: 新加入一个点 \((x,y)\): ...

  4. 【NX二次开发】拉伸的偏置方向猜想与验证

    结论:偏置的方向为曲线方向与拉伸方向的向量叉乘. 在UF_MODL_create_extrusion帮助中有这么一句话:Note that the offset direction is determ ...

  5. 【MySQL】MySQL Workbench 8.0 CE 界面汉化

    汉化前: 找到这个文件: 打开文件,复制下面这段替换进去保存,重新打开软件即可:(*改之前备份一下) <?xml version="1.0"?> <data> ...

  6. Pytorch CNN网络MNIST数字识别 [超详细记录] 学习笔记(三)

    目录 1. 准备数据集 1.1 MNIST数据集获取: 1.2 程序部分 2. 设计网络结构 2.1 网络设计 2.2 程序部分 3. 迭代训练 4. 测试集预测部分 5. 全部代码 1. 准备数据集 ...

  7. 把 STM32 bluepill 变成调试器(daplink)

    在调一块 ARM M0 内核的板子,使用官方的 DEMO 板子来调,板子上集成了 daplink 调试器. 为了方便使用,我把目标板跟 daplink 剪开了,然后用杜邦线把 daplink 跟目标板 ...

  8. .NET 云原生架构师训练营(设计原则与模式)--学习笔记

    在复杂系统的架构设计中引入设计原则与模式,能够极大降低复杂系统开发.和维护的成本 目录 几个问题 为什么要学习设计模式 优良架构设计的具体指标 理解复杂系统 面向对象思想(指导复杂系统的分析.设计.实 ...

  9. 乘风破浪,遇见Visual Studio 2022预览版(Preview),宇宙最强开发者工具首次迎来64位版本

    简介 众所周知,我们从官方新闻来看,对Visual Studio 2022最大的期待莫过于:其是首个64位的Visual Studio,这个宇宙最强开发者工具一脚迈入了新的阶段. https://vi ...

  10. Nexus3搭建Docker等私服

    0.目的 docker私有仓库的搭建,方便后期的CI/CD dotnetcore项目sdk本地缓存,解决微软官方下载缓慢的问题 nuget私有仓库 等 1.环境情况 windows10 Docker ...