wzj52501_图图的旅行

【问题描述】
图图是一个很萌很萌很可爱的好孩纸。
图图计划去 Bzeroth 的精灵王国去旅游, 精灵王国由 n 座城市组成, 第 i
城市有 3 个属性 x[i]w[i]t[i]
在精灵王国的城市之间穿行只能依靠传送阵, 第 i 座城市的传送阵可以将图
图从城市 i 传送到距离城市 i 不超过 w[i]的任意一个城市, 并需要 t[i]的时间完
成传送。 现在图图知道了每个城市的坐标 x[i], 想知道他从城市 s 到城市 t 的最
小时间。
这么难的问题图图当然不会做了, 他想让你帮帮他, 你能解决这个问题
吗?
【输入】
第一行包含 3 个正整数 nst, 表示城市个数, 起点城市和终点城市。
第二行包含 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 ≤ 1525010w[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();

}
原文地址:https://www.cnblogs.com/ling-zhi/p/11759761.html