[NOI2019]弹跳(KD-Tree)

被jump送退役了,很生气。

不过切了这题也进不了队,行吧。

退役后写了一下,看到二维平面应该就是KD树,然后可以在KD树上做最短路,然后建立堆和KDTree。然后每次更新则是直接把最短路上的节点删掉,然后合并KDTree

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+7,M=15e5+7;
struct point{int w,l,r,u,d;}p[N];
struct node{int u,d;};
vector<int>G[N];
int n,m,W,H,now,dis,cnt,rt,tot,hd[N],v[M],nxt[M],w[M],vis[N],d[N],ch[N][4];
bool operator<(node x,node y){return x.d>y.d;}
priority_queue<node>q;
void adde(int x,int y,int z){v[++cnt]=y,nxt[cnt]=hd[x],w[cnt]=z,hd[x]=cnt;}
void add(int fa,int&o,int xl,int xr,int yl,int yr,int x,int y)
{
    if(x<xl||x>xr||y<yl||y>yr)return;
    if(!o)o=++tot;
    if(o!=rt)adde(fa+n,o+n,0);
    if(xl==xr&&yl==yr){adde(o+n,now,0);return;}
    int xm=xl+xr>>1,ym=yl+yr>>1;
    add(o,ch[o][0],xl,xm,yl,ym,x,y);
    add(o,ch[o][1],xl,xm,ym+1,yr,x,y);
    add(o,ch[o][2],xm+1,xr,yl,ym,x,y);
    add(o,ch[o][3],xm+1,xr,ym+1,yr,x,y);
}
void link(int o,int xl,int xr,int yl,int yr,int xL,int xR,int yL,int yR)
{
    if(!o||xR<xl||xL>xr||yR<yl||yL>yr||d[o+n]<=dis)return;
    if(xl>=xL&&xr<=xR&&yl>=yL&&yr<=yR){d[o+n]=dis,q.push((node){o+n,d[o+n]});return;}
    int xm=xl+xr>>1,ym=yl+yr>>1;
    link(ch[o][0],xl,xm,yl,ym,xL,xR,yL,yR);
    link(ch[o][1],xl,xm,ym+1,yr,xL,xR,yL,yR);
    link(ch[o][2],xm+1,xr,yl,ym,xL,xR,yL,yR);
    link(ch[o][3],xm+1,xr,ym+1,yr,xL,xR,yL,yR);
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&W,&H);
    for(int i=1,x,y;i<=n;i++)scanf("%d%d",&x,&y),now=i,add(0,rt,1,W,1,H,x,y);
    for(int i=1;i<=m;i++)
    scanf("%d%d%d%d%d%d",&now,&p[i].w,&p[i].l,&p[i].r,&p[i].u,&p[i].d),G[now].push_back(i);
    memset(d,63,sizeof d);
    d[1]=0,q.push((node){1,0});
    while(!q.empty())
    {
        int u=q.top().u;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=0,x;i<G[u].size();i++)
        x=G[u][i],dis=d[u]+p[x].w,link(rt,1,W,1,H,p[x].l,p[x].r,p[x].u,p[x].d);
        for(int i=hd[u];i;i=nxt[i])if(d[v[i]]>d[u]+w[i])q.push((node){v[i],d[v[i]]=d[u]+w[i]});
    }
    for(int i=2;i<=n;i++)printf("%d\n",d[i]);
}
View Code

 

转载于:https://www.cnblogs.com/hfctf0210/p/11216233.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值