In Touch(dijk+并查集优化)

There are n soda living in a straight line. soda are numbered by 1,2,…,n1,2,…,n from left to right. The distance between two adjacent soda is 1 meter. Every soda has a teleporter. The teleporter of ii-th soda can teleport to the soda whose distance between ii-th soda is no less than lili and no larger than riri. The cost to use ii-th soda's teleporter is cici. 

The 11-st soda is their leader and he wants to know the minimum cost needed to reach ii-th soda (1≤i≤n)(1≤i≤n). 

Input

There are multiple test cases. The first line of input contains an integer TT, indicating the number of test cases. For each test case: 

The first line contains an integer nn (1≤n≤2×105)(1≤n≤2×105), the number of soda. 
The second line contains nn integers l1,l2,…,lnl1,l2,…,ln. The third line contains nn integers r1,r2,…,rnr1,r2,…,rn. The fourth line contains nn integers c1,c2,…,cnc1,c2,…,cn. (0≤li≤ri≤n,1≤ci≤109)(0≤li≤ri≤n,1≤ci≤109)

Output

For each case, output nn integers where ii-th integer denotes the minimum cost needed to reach ii-th soda. If 11-st soda cannot reach ii-the soda, you should just output -1.

Sample Input

1
5
2 0 0 0 1
3 1 1 0 5
1 1 1 1 1

Sample Output

0 2 1 1 -1

        
  

Hint

If you need a larger stack size, 
please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.

其实每个点只更新一次就可以

但是由于我们每次更新都要遍历一个范围

因此我们就不能每次都暴力的跑出更新的值

所以我们就想到使用并查集的方法进行优化

用并查集跑数组的好处就是可跳过没必要的点

从而降低时间复杂度

#define LOCAL
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
int l[200005],r[200005];
long long c[200005];
int father[200005];
int n;
long long dis[200005];
void intal()
{
    for(int i=0;i<=n+5;i++) father[i]=i;
}
struct node
{
    int id;
    long long num;
    node (int p,long long q): id(p),num(q){}
    friend bool operator < (node p,node q)
    {
        return p.num>q.num;
    }
};
int fin(int x)
{
    if(x==father[x]) return x;
    return father[x]=fin(father[x]);
}
void dijk()
{
    memset(dis,0x3f,sizeof(dis));
    priority_queue<node>q;
    dis[1]=0;
    father[1]=2;
    q.push(node(1,c[1]));
    while(q.size())
    {
        //cout<<q.size()<<endl;
        int tmp1=q.top().id;
        long long tmp2=q.top().num;
        q.pop();
        for(int i=1;i>=-1;i-=2)
        {
            int lf,rt;
            lf=tmp1+i*l[tmp1];
            rt=tmp1+i*r[tmp1];
            lf=max(0,lf),lf=min(n+1,lf);
            rt=max(0,rt),rt=min(n+1,rt);
            if(lf>rt) swap(lf,rt);
            for(int j=lf;j<=rt;j++)
            {
               //cout<<"lf"<<lf<<"rt"<<rt<<j<<" "<<fin(j)<<father[2]<<endl;
                j=fin(j);
                if(j>rt||j<0||j>n) break;
                dis[j]=tmp2;
                father[j]=fin(j+1);
                q.push(node(j,tmp2+c[j]));
            }
            //cout<<"wdnmd"<<endl;
        }
    }
}
int main()
{
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    #endif
    int t;  
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        intal();
        for(int i=1;i<=n;i++) scanf("%d",&l[i]);
        for(int i=1;i<=n;i++) scanf("%d",&r[i]);
        for(int i=1;i<=n;i++) scanf("%lld",&c[i]);
        dijk();
        for(int i=1;i<=n;i++)
        {
            if(dis[i]>1e18) printf("-1%c",i==n?'\n':' ');
            else printf("%lld%c",dis[i],i==n?'\n':' ');
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值