$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))$ 。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }