[NOI2019] 弹跳

link

$solution:$

大力线段树即可。

有一个简单做法为在每一个线段树的节点维护一个 $set$ ,线段树存 $x$ 轴, $set$ 维护 $y$ 轴,然后每次暴力取点 $dijkstra$ 即可。

因为线段树上最多 $n\log^2 n$个点,在线段树上取点后还要删除此点,动态维护,不直接连边。

即空间复杂度 $O(n\log^2 n)$ ,时间复杂度 $O((n\log^2 n) \log (n\log^2 n))$ 。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=150001;
priority_queue<pair<int,int> > que;
set<pair<int,int> > s[MAXN<<2];
int dis[MAXN<<2],vis[MAXN<<2],head[MAXN],cnt;
struct spe{
    int x,y;
}g[MAXN];
struct Segment{
    void modify(int k,int l,int r,int x,int y,int id){
        s[k].insert(make_pair(g[id].y,id));
        if(l==r) return;
        int mid=l+r>>1;
        if(x<=mid) modify(k<<1,l,mid,x,y,id);
        if(mid<y) modify(k<<1|1,mid+1,r,x,y,id);
        return;
    }
    void Query(int k,int l,int r,int x,int y,int L,int R,int id){
        if(x<=l&&r<=y){
            set<pair<int,int> >:: iterator it;
            while(!s[k].empty()){
                it=s[k].lower_bound(make_pair(L,-1));
                if(it==s[k].end()||(*it).first>R) break;
                int v=(*it).second;
                if(dis[v]>dis[id]){
                    dis[v]=dis[id];
                    que.push(make_pair(-dis[v],v));
                }s[k].erase(*it);
            }
            return;
        }
        int mid=l+r>>1;
        if(x<=mid) Query(k<<1,l,mid,x,y,L,R,id);
        if(mid<y) Query(k<<1|1,mid+1,r,x,y,L,R,id);
        return;
    }
}segment;
int n,m,w,h;
struct node{
    int u,v,nex;
}x[MAXN<<1];
struct Spe{
    int be,w,l,r,d,u;
}f[MAXN];
void add(int u,int v){
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int main(){
    freopen("jump.in","r",stdin);
    freopen("jump.out","w",stdout);
    memset(head,-1,sizeof(head));
    n=read(),m=read(),w=read(),h=read();
    for(int i=1;i<=n;i++) g[i].x=read(),g[i].y=read(),segment.modify(1,1,w,g[i].x,g[i].x,i);
    for(int i=1;i<=m;i++) f[i].be=read(),f[i].w=read(),f[i].l=read(),f[i].r=read(),f[i].d=read(),f[i].u=read(),add(f[i].be,i);
    memset(dis,127/3,sizeof(dis));
    dis[1]=0;que.push(make_pair(0,1));
    while(!que.empty()){
        int xx=que.top().second;que.pop();
        if(vis[xx]) continue;
        vis[xx]=1;
        if(xx>n){
            segment.Query(1,1,w,f[xx-n].l,f[xx-n].r,f[xx-n].d,f[xx-n].u,xx);
            continue;
        }
        for(int i=head[xx];i!=-1;i=x[i].nex){
            int v=x[i].v+n;
            if(dis[v]>dis[xx]+f[x[i].v].w){
                dis[v]=dis[xx]+f[x[i].v].w;
                que.push(make_pair(-dis[v],v));
            }
        }
    }for(int i=2;i<=n;i++) printf("%d\n",dis[i]);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/si-rui-yang/p/11226654.html