有\(n(n\le2\times10^5)\)個點,每一個點有三個屬性\(l_i,r_i,c_i\)。表示若\(|i-j|\in[l_i,r_i]\),\(i\)到\(j\)有一條長度爲\(c_i\)的單向邊。求從\(1\)出發到各個點的距離。node
線段樹優化建圖後跑Dijkstra便可。git
#include<cstdio> #include<cctype> #include<vector> #include<climits> #include<functional> #include<ext/pb_ds/priority_queue.hpp> inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } const int N=4e5+1; typedef long long int64; int tot,l[N],r[N],c[N],pos[N]; struct Edge { int to,w; }; std::vector<Edge> e[N]; inline void add_edge(const int &u,const int &v,const int &w) { e[u].push_back((Edge){v,w}); } inline void reset() { for(register int i=1;i<=tot;i++) { e[i].clear(); } tot=0; } class SegmentTree { #define mid ((b+e)>>1) private: struct Node { int left,right; }; Node node[N]; int new_node() { node[++tot]=(Node){}; return tot; } public: int root; void build(int &p,const int &b,const int &e) { p=new_node(); if(b==e) { pos[b]=p; return; } build(node[p].left,b,mid); build(node[p].right,mid+1,e); add_edge(p,node[p].left,0); add_edge(p,node[p].right,0); } void link(const int &p,const int &b,const int &e,const int &l,const int &r,const int &x,const int &y) const { if(l>r) return; if(b==l&&e==r) { add_edge(x,p,y); return; } if(l<=mid) link(node[p].left,b,mid,l,std::min(mid,r),x,y); if(r>mid) link(node[p].right,mid+1,e,std::max(mid+1,l),r,x,y); } #undef mid }; SegmentTree sgt; struct Vertex { int id; int64 dis; bool operator > (const Vertex &rhs) const { return dis>rhs.dis; } }; int64 dis[N]; __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q; __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[N]; inline void dijkstra() { for(register int i=1;i<=tot;i++) { p[i]=q.push((Vertex){i,dis[i]=i==pos[1]?0:LLONG_MAX}); } while(!q.empty()&&q.top().dis!=LLONG_MAX) { const int x=q.top().id; q.pop(); for(register unsigned i=0;i<e[x].size();i++) { const int &y=e[x][i].to,&w=e[x][i].w; if(dis[x]+w<dis[y]) { q.modify(p[y],(Vertex){y,dis[y]=dis[x]+w}); } } } q.clear(); } int main() { for(register int T=getint();T;T--) { const int n=getint(); sgt.build(sgt.root,1,n); for(register int i=1;i<=n;i++) l[i]=getint(); for(register int i=1;i<=n;i++) r[i]=getint(); for(register int i=1;i<=n;i++) c[i]=getint(); for(register int i=1;i<=n;i++) { sgt.link(1,1,n,std::max(1,i-r[i]),i-l[i],pos[i],c[i]); sgt.link(1,1,n,i+l[i],std::min(i+r[i],n),pos[i],c[i]); } dijkstra(); for(register int i=1;i<=n;i++) { printf("%lld%c",dis[pos[i]]!=LLONG_MAX?dis[pos[i]]:-1," \n"[i==n]); } reset(); } return 0; }