第一眼就是 $KDtree$ 优化建图
然而,空间只有 $128mb$,开不下  
时间不吃紧,考虑直接跑 $Dijkstra$
$Dijkstra$ 中存储的是起点到每个输入时给出的矩阵的最短距离
当取出堆顶时就将这个矩阵中所有点 "裂开",并更新每一个小点的答案
如果该点在之前已经被一个最短路更短的矩阵更新过了,就不扩展它
否则,扩展每一个分裂出的点,将新的矩阵加入优先队列中即可
一个重要的优化就是每次 "分裂" 一个矩阵时要在 $KDtree$ 中将对应节点都删掉,加快下一次查询 
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 2000000
#define inf 100000000
#define lson t[now].ch[0]
#define rson t[now].ch[1]
#define ll long long
using namespace std; struct Edge {
int t,x1,y1,x2,y2;
Edge(int t=0,int x1=0,int y1=0,int x2=0,int y2=0):t(t),x1(x1),y1(y1),x2(x2),y2(y2){}
};
struct Data {
int ch[2],minv[2],maxv[2],siz,id,p[2];
}t[maxn],arr[maxn];
struct P {
int dis,id;
P(int dis=0,int id=0):dis(dis),id(id) {}
bool operator<(P b) const {
return b.dis<dis;
}
};
vector<int>G[maxn];
priority_queue<P>Q;
vector<Edge>edges; int d,cnt,len;
int dis[maxn],answer[maxn],nd[maxn],vis[maxn];
void Min(int &a,int b) {
if(b<a) a=b;
}
void Max(int &a,int b) {
if(b>a) a=b;
}
bool cmp(Data i,Data j) {
return i.p[d]==j.p[d]?i.p[d^1]<j.p[d^1]:i.p[d]<j.p[d];
}
void pushup(int now) {
t[now].minv[0]=t[now].minv[1]=inf,t[now].maxv[0]=t[now].maxv[1]=-inf;
for(int i=0;i<2;++i) {
if(lson) {
Min(t[now].minv[0],t[lson].minv[0]),Min(t[now].minv[1],t[lson].minv[1]),
Max(t[now].maxv[0],t[lson].maxv[0]),Max(t[now].maxv[1],t[lson].maxv[1]);
}
if(rson) {
Min(t[now].minv[0],t[rson].minv[0]),Min(t[now].minv[1],t[rson].minv[1]),
Max(t[now].maxv[0],t[rson].maxv[0]),Max(t[now].maxv[1],t[rson].maxv[1]);
}
}
}
void build(int l,int r,int &now,int o) {
now=++cnt;
if(l==r) {
t[now].siz=1, t[now].id=arr[l].id;
t[now].p[0]=t[now].minv[0]=t[now].maxv[0]=arr[l].p[0];
t[now].p[1]=t[now].minv[1]=t[now].maxv[1]=arr[l].p[1];
return;
}
int mid=(l+r)>>1;
d=o,nth_element(arr+l,arr+mid,arr+1+r,cmp);
build(l,mid,lson,o^1);
if(r>mid) build(mid+1,r,rson,o^1);
pushup(now),t[now].siz=t[lson].siz+t[rson].siz;
}
void dfs(int now,int x1,int y1,int x2,int y2) {
if(t[now].minv[0]>y1||t[now].maxv[0]<x1||t[now].minv[1]>y2||t[now].maxv[1]<x2 || !t[now].siz) return;
if(t[now].id) {
nd[++len]=t[now].id;
t[now].siz=0;
return;
}
if(lson) dfs(lson,x1,y1,x2,y2);
if(rson) dfs(rson,x1,y1,x2,y2);
t[now].siz=t[lson].siz+t[rson].siz;
}
void debug(int now) {
if(!now) return;
debug(lson), printf("%d %d %d %d\n",t[now].minv[0],t[now].maxv[0],t[now].minv[1],t[now].maxv[1]),debug(rson);
}
int main(){
// setIO("input");
int n,m,w,h,rt;
scanf("%d%d%d%d",&n,&m,&w,&h);
for(int i=1;i<=n;++i) scanf("%d%d",&arr[i].p[0],&arr[i].p[1]),arr[i].id=i;
build(1,n,rt,0);
for(int i=1;i<=m;++i) {
int a,b,c,d,e,f;
scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f), edges.push_back(Edge(b,c,d,e,f)), G[a].push_back(i-1);
}
answer[1]=0,vis[1]=1;
for(int i=0;i<G[1].size();++i) {
int to=G[1][i];
dis[to]=edges[to].t, Q.push(P(edges[to].t, to));
}
while(!Q.empty()) {
P e=Q.top(); Q.pop();
int cn=e.dis;
len=1,dfs(rt, edges[e.id].x1,edges[e.id].y1,edges[e.id].x2,edges[e.id].y2);
for(int i=1;i<=len;++i) {
int cur=nd[i];
if(vis[cur]) continue;
vis[cur]=1, answer[cur]=cn;
for(int j=0;j<G[cur].size();++j) {
int to=G[cur][j];
dis[to] = cn + edges[to].t;
Q.push(P(dis[to], to));
}
}
}
for(int i=2;i<=n;++i) printf("%d\n",answer[i]);
return 0;
}

  

luogu 5471 [NOI2019]弹跳 KDtree + Dijkstra的更多相关文章

  1. [NOI2019]弹跳(KD-Tree/四分树/线段树套平衡树 优化建图+Dijkstra)

    本题可以用的方法很多,除去以下三种我所知道的就还有至少三种. 方法一:类似线段树优化建图,将一个平面等分成四份(若只有一行或一列则等分成两份),然后跑Dijkstra即可.建树是$O(n\log n) ...

  2. luogu P5471 [NOI2019]弹跳

    luogu 因为是一个点向矩形区域连边,所以可以二维数据结构优化连边,但是会MLE.关于维护矩形的数据结构还有\(KD-Tree\),所以考虑\(KDT\)优化连边,空间复杂度\(m\sqrt n\) ...

  3. 【题解】Luogu P5471 [NOI2019]弹跳

    原题传送门 先考虑部分分做法: subtask1: 暴力\(O(nm)\)枚举,跑最短路 subtask2: 吧一行的点压到vector中并排序,二分查找每一个弹跳装置珂以到达的城市,跑最短路 sub ...

  4. [NOI2019]弹跳(KD-Tree)

    被jump送退役了,很生气. 不过切了这题也进不了队,行吧. 退役后写了一下,看到二维平面应该就是KD树,然后可以在KD树上做最短路,然后建立堆和KDTree.然后每次更新则是直接把最短路上的节点删掉 ...

  5. [NOI2019] 弹跳

    题意: 给你平面上的$n$个点,共有$m$个弹跳装置. 每个弹跳装置可以从点$p_{i}$以$t_{i}$的代价跳到矩形$(L_{i},D_{i}),(R_{i},U_{i})$中的任何一个点. 现在 ...

  6. 洛谷 P5471 - [NOI2019] 弹跳(二维线段树优化建图+堆优化存边)

    题面传送门 一道非常有意思的题(大概可以这么形容?) 首先看到这类一个点想一个区域内连边的题目可以很自然地想到线段树优化建图,只不过这道题是二维的,因此需要使用二维线段树优化建图,具体来说,我们外层开 ...

  7. Luogu P5469 [NOI2019]机器人 (DP、多项式)

    不用FFT的多项式(大雾) 题目链接: https://www.luogu.org/problemnew/show/P5469 (这题在洛谷都成绿题了海星) 题解: 首先我们考虑,一个序列位置最右边的 ...

  8. Luogu P5468 [NOI2019]回家路线 (斜率优化、DP)

    题目链接: (luogu) https://www.luogu.org/problemnew/show/P5468 题解: 爆long long毁一生 我太菜了,这题这么简单考场上居然没想到正解-- ...

  9. 题解 [NOI2019]弹跳

    题目传送门 题目大意 给出 \(n\) 做城市,每座城市都有横纵坐标 \(x,y\).现在给出 \(m\) 个限制 \(p,t,l,r,d,u\),表示从 \(p\) 城市出发,可以花费 \(t\) ...

随机推荐

  1. C#采集:图灵机器人信息

    Dictionary<string, string> users = new Dictionary<string, string>(); users.Add("use ...

  2. JDK8中接口的新特性

    在JDK8环境中,接口中的方法不再是只能有抽象方法,还可以有静态方法和default方法.实现类只需要实现它的抽象方法即可,JDK8中的接口有愈发向抽象类靠拢的感觉. 关于静态方法和默认方法作如下简述 ...

  3. [Git] 021 来一颗“恶魔果实”?

    0. 前言 需要新的功能时,一般会新建一条 "feature" 分支(尴尬的是,我第一眼看时,看成了 "future") 在 "feature&quo ...

  4. kubeadm初始化kubernetes集群

    有两种方式安装集群: 1.手动安装各个节点的各个组件,安装极其复杂困难. 2.使用工具:kubeadm kubeadm 是官方提供的专门部署集群的管理工具. 1. 在kubeadm下每个节点都需要安装 ...

  5. 正反向代理、负载均衡、Nginx配置实现

    一.正反向代理 1.前提 我们曾经使用翻墙软件,访问google:使用了代理软件时,需要在浏览器选项中配置代理的地址,我们仅仅有代理这个概念,并不清楚代理还有正向和反向之分. 2.正向代理(代替客户端 ...

  6. 通过Spark Streaming处理交易数据

    Apache Spark 是加州大学伯克利分校的 AMPLabs 开发的开源分布式轻量级通用计算框架. 由于 Spark 基于内存设计,使得它拥有比 Hadoop 更高的性能(极端情况下可以达到 10 ...

  7. 中标麒麟(linux)mysql配置记录

    刚装好mysql时,使用正常,后来再次使用时,连接不成功.(虚拟机中) 配置网络有问题, 1.我将ifcfg-*的两个文件备份后删除了. 2.点击右下角的小电脑,重新新建一个网络连接.把网络接入主机的 ...

  8. 剑指offer-平衡二叉树-python

    题目描述 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 思路: 平衡二叉树 (AVL)平衡二叉树是一种二叉排序树,其中每个结点的左子树和右子树的高度差至多等于1.它是一种高度平衡的二叉排序树.意思是 ...

  9. getchar、putchar、puts、gets

    getchar(字符)  输入获取一个字符 putchar(字符)  输出控制台一个字符 scanf()格式化输入 printf() 格式化输出 gets(arr) 输入一个字符串给已经声明的数组ar ...

  10. spark(3)

    0.spark -------------------------------------------- transformation map filter repartition spark核心AP ...