原題傳送門node
先考慮部分分作法:c++
暴力$O(nm)$枚舉,跑最短路算法
吧一行的點壓到vector中並排序,二分查找每個彈跳裝置珂以到達的城市,跑最短路數據結構
看見是一個鏈,天然而然的能夠想到線段樹優化建圖,跑最短路優化
上面是72pts的暴力作法,其中subtask3的作法給了咱們了一些提示,這題要用數據結構優化建圖:spa
在橫軸上開一顆線段樹,線段樹每一個節點上是一個存pair的set,存的是$[l,r]$區間內有第$id$個點($px[id] \in [l,r]$),這個點的縱座標是$py[id]$(pair要把縱座標放前面)code
相似線段樹優化建圖,咱們要建立一些虛擬節點:對於第$i$個彈跳裝置,咱們建立一個編號爲$i+n$的虛擬點,且到虛擬點的距離爲所用時間$T[i]$排序
咱們從$1$號點跑最短路。假如如今對頂是$x$號節點,當$x \leq n$時,咱們更新起點爲$x$的彈跳裝置的虛擬點的dis,並扔進堆;不然就在線段樹上先找到$[L[x-n],R[x-n]]$這個區間($x-n$就是該虛擬點所對應彈跳裝置的編號),在這個區間所含的線段樹節點上二分出$D[x-n] \leq py[id] \leq U[x-n]$中的節點,嘗試更新dis,若是成功加入隊列,無論成不成功,都從set中刪除(根據dij的特性)。隊列
這樣最後輸出dis[2~n]就好了get
這個算法的複雜度是$O((n+m)\log(n+m)+n\log^2 n)$,常數略(da)大(dao)一(mei)點(jiu)
($(n+m)\log(n+m)$是$n+m$個點dij的複雜度,$n\log^2 n$是$n$個節點,每一個拆成$\log n$個,在set中insert,lowerbound,erase的複雜度)
#include <bits/stdc++.h> #define N 70005 #define M 150005 #define getchar nc using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int read() { register int x=0,f=1;register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f; } inline void write(register int x) { if(!x)putchar('0');if(x<0)x=-x,putchar('-'); static int sta[20];register int tot=0; while(x)sta[tot++]=x%10,x/=10; while(tot)putchar(sta[--tot]+48); } int n,m,w,h; int px[N],py[N]; int P[M],T[M],L[M],R[M],D[M],U[M]; set<pair<int,int> > s[N<<2]; vector<int> nv[N]; struct node{ int dis,pos; bool operator < (const node &x) const{ return x.dis<dis; } }; priority_queue<node> q; int dis[N+M],vis[N+M]; inline void modify(register int x,register int l,register int r,register int id) { s[x].insert(make_pair(py[id],id)); if(l==r) return; int mid=l+r>>1; if(px[id]<=mid) modify(x<<1,l,mid,id); else modify(x<<1|1,mid+1,r,id); } inline void change(register int x,register int l,register int r,register int id) { if(L[id]<=l&&r<=R[id]) { set<pair<int,int> >::iterator it; while(19260817) { it=s[x].lower_bound(make_pair(D[id],-1)); if(it==s[x].end()||it->first>U[id]) break; int to=it->second; if(dis[to]>dis[id+n]) { dis[to]=dis[id+n]; q.push((node){dis[to],to}); } s[x].erase(it); } return; } int mid=l+r>>1; if(L[id]<=mid) change(x<<1,l,mid,id); if(R[id]>mid) change(x<<1|1,mid+1,r,id); } int main() { n=read(),m=read(),w=read(),h=read(); for(register int i=1;i<=n;++i) { px[i]=read(),py[i]=read(); if(i!=1) modify(1,1,w,i); } for(register int i=1;i<=m;++i) { P[i]=read(),T[i]=read(),L[i]=read(),R[i]=read(),D[i]=read(),U[i]=read(); nv[P[i]].push_back(i+n); } for(register int i=1;i<=n;++i) dis[i]=1926081700,vis[i]=0; dis[1]=0; q.push((node){0,1}); while(!q.empty()) { node tmp=q.top(); q.pop(); int x=tmp.pos; if(vis[x]) continue; vis[x]=1; if(x<=n) { for(register int i=0;i<nv[x].size();++i) { int y=nv[x][i]; dis[y]=dis[x]+T[y-n]; q.push((node){dis[y],y}); } } else change(1,1,w,x-n); } for(register int i=2;i<=n;++i) write(dis[i]),puts(""); return 0; }