图图的旅行

【题目描述】:

图图计划去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 的最小时间,保证至少存在一组合法解。

【样例输入】:

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。

【时间限制、数据范围及描述】:

时间:1s 空间:256M

对于30%的数据,1≤n≤2501,所有的t[i]均相等。

对于60%的数据,1≤n≤2501。

对于100%的数据,1≤n≤152501,0≤w[i],t[i],|x[i]|≤10^9,保证x[i]严格递增。

Analysis:

线段树优化建图:

点编号:1~n
线段树(区间)点编号:>n

Code:

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>

using namespace std;

typedef long long ll;
typedef pair<ll,int> PII;

const int N=1e6+5;

int n,S,T,idx;
int x[N],w[N],t[N];
ll dis[N<<2];
bool st[N<<2];
int h[N<<2];

struct node
{
    int nxt,to,w;
}e[N<<3];
struct Tree
{
    int l,r;
}tr[N<<3];

void add(int nxt,int to,int w)
{
    e[++idx].nxt=h[nxt];
    e[idx].to=to;
    e[idx].w=w;
    h[nxt]=idx;
}

void build(int u,int l,int r)
{
    tr[u].l=l;tr[u].r=r;
    if (l==r)
    {
        add(u+n,l,0);
        return;
    }
    int mid=(l+r)>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    add(u+n,(u<<1)+n,0);
    add(u+n,(u<<1|1)+n,0);
}
void modify(int u,int x,int y,int p,int w)
{
    int l=tr[u].l,r=tr[u].r;
    if (l>=x && r<=y)
    {
        add(p,u+n,w);
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)modify(u<<1,x,y,p,w);
    if(y>mid)modify(u<<1|1,x,y,p,w);
}

ll dijk()
{
    memset(dis,0x7f,sizeof(dis));
    dis[S]=0;
    priority_queue<PII,vector<PII>,greater<PII>> q;
    q.push({0,S});

    while(q.size())
    {
        int u=q.top().second;
        q.pop();

        if(st[u])continue;
        st[u]=1;

        for(int i=h[u];~i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                q.push({dis[v],v});
            }
        }
    }
    return dis[T];
}
int main()
{   
    scanf("%d%d%d",&n,&S,&T);

    for(int i=1;i<=n;++i)scanf("%d",&x[i]);
    for(int i=1;i<=n;++i)scanf("%d",&w[i]);
    for(int i=1;i<=n;++i)scanf("%d",&t[i]);

    memset(h,-1,sizeof(h));
    
    build(1,1,n);
    
    for(int i=1;i<=n;++i)
    {
        int l=lower_bound(x+1,x+n+1,x[i]-w[i])-x;
        int r=upper_bound(x+1,x+n+1,x[i]+w[i])-x-1;
        modify(1,l,r,i,t[i]);
    }
    printf("%lld\n",dijk());
    return 0;
}
posted @ 2022-10-04 11:02  FighterQ  阅读(48)  评论(0)    收藏  举报