题意:w×h网格中有n个点,m条边。每条边可以从p点花费t时间到一个矩形中的任意点,求1号点到每个点的最少时间。

\(1<=w,h<=n<=70000,1<=m<=150000\)

时间2s,空间128M

本题如果放在序列上,使用线段树建图,可以做到\(O(mlogn)\)的复杂度,通过数据分治可以获得72分。

对于二维问题可以想到将线段树变为二维线段树,然而会被卡空间。

考虑此题暴力Dij的本质:就是每次找最小的点,然后把一个矩形中大于z的数都改为z,再删除这个点。

看到矩形修改,可以想到KD树。

KD树的空间复杂度是\(O(n)\)的,很优秀。

在矩形修改时,采用类似线段树的方法:如果当前矩形与修改的矩形没有交,就直接返回。如果被包含,则直接打标记。

但与线段树不同的:还需要考虑当前的点是否在矩形内,如果在则直接修改这个点。

这就是KD树处理矩形的方法。

时间复杂度:\(O(m\sqrt{n})\)。

删除一个点可以打一个特殊标记实现。

把这个写上后,会发现超时。

考虑剪枝:如果z大于当前点的标记,就直接返回。

这样就能过了。

代码:

#include <stdio.h>
#include <stdlib.h>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
struct SPx
{
int x,y,i;
SPx(){}
SPx(int X,int Y,int I)
{
x=X;y=Y;i=I;
}
};
int cmpx(const void*a,const void*b)
{
return ((SPx*)a)->x-((SPx*)b)->x;
}
int cmpy(const void*a,const void*b)
{
return ((SPx*)a)->y-((SPx*)b)->y;
}
int cl[70010],cr[70010],fa[70010],lx[70010],rx[70010],ly[70010],ry[70010];
int zx[70010],wz[70010],qz[70010],ld[70010],inf=2000000000,root;
bool bk[70010];
void update(int x)
{
if(bk[x])
zx[x]=inf,wz[x]=-1;
else
zx[x]=qz[x],wz[x]=x;
if(cl[x]!=0&&wz[cl[x]]!=-1&&zx[cl[x]]<=zx[x])
zx[x]=zx[cl[x]],wz[x]=wz[cl[x]];
if(cr[x]!=0&&wz[cr[x]]!=-1&&zx[cr[x]]<=zx[x])
zx[x]=zx[cr[x]],wz[x]=wz[cr[x]];
}
void pur(int x,int y)
{
if(ld[x]!=-1&&y>=ld[x])
return;
ld[x]=y;
if(qz[x]>y)qz[x]=y;
if(zx[x]>y)zx[x]=y;
}
void pushdown(int x)
{
if(ld[x]==-1)return;
if(cl[x]!=0)pur(cl[x],ld[x]);
if(cr[x]!=0)pur(cr[x],ld[x]);
ld[x]=-1;
}
void clean(int x)
{
if(fa[x]!=0)
clean(fa[x]);
pushdown(x);
}
void del(int x)
{
clean(x);
bk[x]=true;
for(int i=x;i!=0;i=fa[i])
update(i);
}
int buix(SPx sz[70010],int l,int r);
int buiy(SPx sz[70010],int l,int r);
void pushup(int rt)
{
if(cl[rt]!=0)
{
lx[rt]=min(lx[rt],lx[cl[rt]]);rx[rt]=max(rx[rt],rx[cl[rt]]);
ly[rt]=min(ly[rt],ly[cl[rt]]);ry[rt]=max(ry[rt],ry[cl[rt]]);
fa[cl[rt]]=rt;
}
if(cr[rt]!=0)
{
lx[rt]=min(lx[rt],lx[cr[rt]]);rx[rt]=max(rx[rt],rx[cr[rt]]);
ly[rt]=min(ly[rt],ly[cr[rt]]);ry[rt]=max(ry[rt],ry[cr[rt]]);
fa[cr[rt]]=rt;
}
}
bool fugai(int Lx,int Rx,int Ly,int Ry,int lx,int rx,int ly,int ry)
{
return Lx<=lx&&rx<=Rx&&Ly<=ly&&ry<=Ry;
}
bool fenli(int Lx,int Rx,int Ly,int Ry,int lx,int rx,int ly,int ry)
{
return Lx>rx||lx>Rx||Ly>ry||ly>Ry;
}
int X[70010],Y[70010];
int buix(SPx sz[70010],int l,int r)
{
if(l>=r)return 0;
qsort(sz+l,r-l,sizeof(SPx),cmpx);
int m=(l+r-1)>>1,rt=sz[m].i;
lx[rt]=rx[rt]=sz[m].x;
ly[rt]=ry[rt]=sz[m].y;
cl[rt]=buiy(sz,l,m);
cr[rt]=buiy(sz,m+1,r);
pushup(rt);
return rt;
}
int buiy(SPx sz[70010],int l,int r)
{
if(l>=r)return 0;
qsort(sz+l,r-l,sizeof(SPx),cmpy);
int m=(l+r-1)>>1,rt=sz[m].i;
lx[rt]=rx[rt]=sz[m].x;
ly[rt]=ry[rt]=sz[m].y;
cl[rt]=buix(sz,l,m);
cr[rt]=buix(sz,m+1,r);
pushup(rt);
return rt;
}
void songc(int i,int Lx,int Rx,int Ly,int Ry,int z)
{
if(ld[i]!=-1&&z>ld[i])
return;
if(fenli(Lx,Rx,Ly,Ry,lx[i],rx[i],ly[i],ry[i]))
return;
if(fugai(Lx,Rx,Ly,Ry,lx[i],rx[i],ly[i],ry[i]))
{
pur(i,z);
return;
}
pushdown(i);
if(fugai(Lx,Rx,Ly,Ry,X[i],X[i],Y[i],Y[i]))
{
if(qz[i]>z)
qz[i]=z;
update(i);
}
if(cl[i]!=0)
songc(cl[i],Lx,Rx,Ly,Ry,z);
if(cr[i]!=0)
songc(cr[i],Lx,Rx,Ly,Ry,z);
update(i);
}
void dfs(int u)
{
if(cl[u]!=0)
dfs(cl[u]);
if(cr[u]!=0)
dfs(cr[u]);
update(u);
}
int dis[70010];
int fr[70010],ne[150010],x1[150010],x2[150010],y1[150010],y2[150010],w[150010],bs=0;
void addb(int a,int lx,int rx,int ly,int ry,int b)
{
x1[bs]=lx;x2[bs]=rx;
y1[bs]=ly;y2[bs]=ry;
w[bs]=b;
ne[bs]=fr[a];
fr[a]=bs++;
}
SPx sz[70010];
void dij(int u,int n)
{
for(int i=1;i<=n;i++)
sz[i]=SPx(X[i],Y[i],i);
root=buix(sz,1,n+1);
for(int i=1;i<=n;i++)
qz[i]=inf;
qz[u]=0;
dfs(root);
while(1)
{
int t=wz[root],x=zx[root];
if(t==-1)break;
del(t);dis[t]=x;
for(int i=fr[t];i!=-1;i=ne[i])
songc(root,x1[i],x2[i],y1[i],y2[i],x+w[i]);
}
}
int main()
{
wz[0]=-1;
int n,m,w,h;
scanf("%d%d%d%d",&n,&m,&w,&h);
for(int i=1;i<=n;i++)
scanf("%d%d",&X[i],&Y[i]);
for(int i=1;i<=n;i++)
fr[i]=ld[i]=-1;
for(int i=0;i<m;i++)
{
int p,t,l,r,d,u;
scanf("%d%d%d%d%d%d",&p,&t,&l,&r,&d,&u);
addb(p,l,r,d,u,t);
}
dij(1,n);
for(int i=2;i<=n;i++)
printf("%d\n",dis[i]);
return 0;
}

「NOI2019」弹跳(KD树)的更多相关文章

  1. LOJ 3159: 「NOI2019」弹跳

    题目传送门:LOJ #3159. 题意简述: 二维平面上有 \(n\) 个整点,给定每个整点的坐标 \((x_i,y_i)\). 有 \(m\) 种边,第 \(i\) 种边从 \(p_i\) 号点连向 ...

  2. loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点

    loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点 链接 loj 思路 用交错关系建出图来,发现可以直接缩点,拓扑统计. 完了吗,不,瓶颈在于边数太多了,线段树优化建图. 细节 ...

  3. loj3161「NOI2019」I 君的探险(随机化,整体二分)

    loj3161「NOI2019」I 君的探险(随机化,整体二分) loj Luogu 题解时间 对于 $ N \le 500 $ 的点,毫无疑问可以直接 $ O(n^2) $ 暴力询问解决. 考虑看起 ...

  4. LOJ 2551 「JSOI2018」列队——主席树+二分

    题目:https://loj.ac/problem/2551 答案是排序后依次走到 K ~ K+r-l . 想维护一个区间排序后的结果,使得可以在上面二分.求和:二分可以知道贡献是正还是负. 于是想用 ...

  5. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  6. 「模板」「讲解」Treap名次树

    Treap实现名次树 前言 学平衡树的过程可以说是相当艰难.浏览Blog的过程中看到大量指针版平衡树,不擅长指针操作的我已经接近崩溃.于是,我想着一定要写一篇非指针实现的Treap的Blog. 具体如 ...

  7. 「BZOJ3083」遥远的国度(树剖换根

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 4859  Solved: 1372[Submit][Status][Discu ...

  8. LG5536 「XR-3」核心城市 树的直径

    问题描述 LG5536 题解 两次 \(\mathrm{dfs}\) 求树的直径. 然后找到树的直径的中点. 然后按照 子树中最深的点深度-自己深度 排序,贪心选取前 \(k\) 个. \(\math ...

  9. LG2495 「SDOI2011」消耗战 虚树

    问题描述 LG2495 题解 虚树 \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; #define int l ...

随机推荐

  1. [DEBUG] ubuntu pip安装成功却无法import

    我的pip经常出问题,我也不知道为啥..今天搞啥啥坏=.= 问题: pip自动安装显示成功,在交互环境下却无法import ==========================踩坑========== ...

  2. C++基础--函数重载

    函数重载定义: 在相同的作用域中具有相同的函数名而函数形参列表(参数类型.参数个数.参数顺序)不同的两个函数,称之为函数重载.注意:函数返回值类型并不是重载的条件. 函数重载优点: 可以使用相同的函数 ...

  3. T100——错误信息提示传入参数显示

    LET l_str1 = l_xccc.xccc901LET l_str2 = l_inat015LET l_str = l_str1.trim(),'|',l_str2.trim() CALL cl ...

  4. Activate注解

    Activate注解 被该注解修饰的接口,扩展类可能会被加载 ProtocolFilterWrapper.buildInvokerChain @Documented @Retention(Retent ...

  5. python中集合set,字典dict和列表list的区别以及用法

    python中set代表集合,list代表列表,dict代表字典 set和dict的区别在于,dict是存储key-value,每一个key都是唯一的,set相对于dict存储的是key,且key是唯 ...

  6. 分布式服务追踪与调用链 Zikpin

    分布式服务追踪与调用链系统产生的背景 在为服务中,如果服务与服务之间的依赖关系非常复杂,如果某个服务出现了一些问题,很难追查到原因,特别是服务与服务之间调用的时候. 在微服务系统中,随着业务的发展,系 ...

  7. Linux下如何查看tomcat是否启动、查看tomcat启动日志

    在Linux系统下,重启Tomcat使用命令的操作! 1.首先,进入Tomcat下的bin目录 cd /usr/local/tomcat/bin 使用Tomcat关闭命令 ./shutdown.sh ...

  8. (九)mybatis之延迟加载

    一.为什么要使用延迟加载? 使用延迟加载的意义 在进行数据查询时,为了提高数据库查询性能,尽量使用单表查询,因为单表查询比多表关联查询速度快. 如果查询单表就可以满足需求,一开始先查询单表,当需要关联 ...

  9. ASP.NET全局编码和语言

    // /*--------------- // //  使用地方:ASP.NET 项目 // //   // // 文件名: // // 文件功能描述:可控制整个项目的一个统一编码格式和语言文字显示 ...

  10. Swagger 实践 <二>

    1. 新建.netCore WebApi 项目(选择Angular).按照上一篇的加上Swage 文档,使http://localhost:11934/swagger/v1/swagger.json  ...