【问题描述】
图图是一个很萌很萌很可爱的好孩纸。
图图计划去 Bzeroth 的精灵王国去旅游, 精灵王国由 n 座城市组成, 第 i 座
城市有 3 个属性 x[i], w[i], t[i]。
在精灵王国的城市之间穿行只能依靠传送阵, 第 i 座城市的传送阵可以将图
图从城市 i 传送到距离城市 i 不超过 w[i]的任意一个城市, 并需要 t[i]的时间完
成传送。 现在图图知道了每个城市的坐标 x[i], 想知道他从城市 s 到城市 t 的最
小时间。
这么难的问题图图当然不会做了, 他想让你帮帮他, 你能解决这个问题
吗?
【输入】
第一行包含 3 个正整数 n、 s、 t, 表示城市个数, 起点城市和终点城市。
第二行包含 n 个整数 x[i], 表示第 i 座城市的坐标。
第三行包含 n 个整数 w[i], 表示第 i 座城市的传送距离。
第四行包含 n 个整数 t[i], 表示第 i 座城市的传送时间。
【输出】
请输出从城市 s 到城市 t 的最小时间, 保证至少存在一组合法解。
【输入输出样例】
trip.in | trip.out |
7 3 7 -1 0 1 2 3 5 10 11 0 1 1 4 10 2 3 1 1 1 2 4 5 |
7 |
【样例解释】
路线为 3 → 4 → 5 → 1 → 7, 时间之和为 7。
【数据范围】
对于 30%的数据, 1 ≤ n ≤ 2501, 所有的 t[i]均相等。
对于 60%的数据, 1 ≤ n ≤ 2501。
对于 100%的数据, 1 ≤ n ≤ 152501, 0≤w[i], t[i], |x[i]|≤109, 保证 x[i]严
格递增。
利用线段树结构优化建边
建完就是最短路了
二分确定一个点能到达的最左最右的点
另外,此题码量稍大,数组大小玄学
#include<iostream> #include<cstdio> #define ri register int #define u int namespace opt { inline u in() { u x(0),f(1); char s(getchar()); while(s<'0'||s>'9') { if(s=='-') f=-1; s=getchar(); } while(s>='0'&&s<='9') { x=(x<<1)+(x<<3)+s-'0'; s=getchar(); } return x*f; } } using opt::in; #define NN 152505 #define MM (152405*4) #define XX (152405*4) #include<algorithm> #include<cstring> #include<queue> namespace dj_ { using std::queue; typedef std::pair<u,u> p; std::priority_queue<p,std::vector<p>,std::greater<p> > q; u h[XX],cnt; long long d[XX]; struct node { u to,next,va; } a[MM<<2]; inline void add(const u &x,const u &y,const u &v) { a[++cnt].to=y,a[cnt].next=h[x],a[cnt].va=v,h[x]=cnt; } void run(const u &x) { d[x]=0,q.push(p(0,x)); while(!q.empty()) { u _x(q.top().second),_dic(q.top().first); q.pop(); if(_dic>d[_x]) continue; for(ri i(h[_x]); i; i=a[i].next) { u _y(a[i].to); if(d[_y]>d[_x]+a[i].va) { d[_y]=a[i].va+d[_x]; q.push(p(d[_y],_y)); } } } } } namespace xds { u to[NN]; void build(const u &rt,const u &l,const u &r) { dj_::d[rt]=((long long)(1)<<60); if(l==r) { to[l]=rt; return; } u mid((l+r)>>1); dj_::add(rt,rt<<1,0); dj_::add(rt,rt<<1|1,0); build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void add(const u &rt,const u &l,const u &r,const u &x,const u &y,const u &st,const u &va) { if(l>=x&&r<=y) { dj_::add(st,rt,va); return; } u mid((l+r)>>1); if(mid>=x) { add(rt<<1,l,mid,x,y,st,va); } if(y>=mid+1) { add(rt<<1|1,mid+1,r,x,y,st,va); } } } namespace mainstay { using xds::to; u N,S,T; struct node { u d,t,r; } a[NN]; u erf(const u &l,const u &r,const u &x,const u &k) { u _l(l),_r(r),_re(-1); if(!k) { while(_l<=_r) { u mid((_l+_r)>>1); if(a[mid].d>=x) { _re=mid,_r=mid-1; } else _l=mid+1; } } else while(_l<=_r) { u mid((_l+_r)>>1); if(a[mid].d<=x) { _re=mid,_l=mid+1; } else _r=mid-1; } return _re; } inline void solve() { N=in(),S=in(),T=in(); for(ri i(1); i<=N; ++i) a[i].d=in(); for(ri i(1); i<=N; ++i) a[i].r=in(); for(ri i(1); i<=N; ++i) a[i].t=in(); xds::build(1,1,N); for(ri i(1); i<=N; ++i) { u _l(erf(1,N,a[i].d-a[i].r,0)); u _r(erf(1,N,a[i].d+a[i].r,1)); xds::add(1,1,N,_l,_r,to[i],a[i].t); } dj_::run(to[S]),printf("%lld",dj_::d[to[T]]); } } int main() { //freopen("trip.in","r",stdin); //freopen("trip.out","w",stdout); mainstay::solve(); }