Problem Description
There are n soda living in a straight line. soda are numbered by
1,2,…,n
from left to right. The distance between two adjacent soda is 1 meter. Every soda has a teleporter. The teleporter of
i
-th soda can teleport to the soda whose distance between
i
-th soda is no less than
li
and no larger than
ri
. The cost to use
i
-th soda's teleporter is
ci
.
The 1 -st soda is their leader and he wants to know the minimum cost needed to reach i -th soda (1≤i≤n) .
The 1 -st soda is their leader and he wants to know the minimum cost needed to reach i -th soda (1≤i≤n) .
Input
There are multiple test cases. The first line of input contains an integer
T
, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤2×105) , the number of soda.
The second line contains n integers l1,l2,…,ln . The third line contains n integers r1,r2,…,rn . The fourth line contains n integers c1,c2,…,cn . (0≤li≤ri≤n,1≤ci≤109)
The first line contains an integer n (1≤n≤2×105) , the number of soda.
The second line contains n integers l1,l2,…,ln . The third line contains n integers r1,r2,…,rn . The fourth line contains n integers c1,c2,…,cn . (0≤li≤ri≤n,1≤ci≤109)
Output
For each case, output
n
integers where
i
-th integer denotes the minimum cost needed to reach
i
-th soda. If
1
-st soda cannot reach
i
-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 -1HintIf you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
这题的难点主要在于边的条数过多,不能像普通的最短路那样子跑。
不过此题的特点在于对于每个点来说,从这个点出去能到的任何点这个过程的花费是相同的,都是cost[i]
于是假设到达该点的距离为dis[i]则从该点能到的任何点j的值都是dis[j]=min(dis[j],dis[i]+cost[i]);
于是只要按照dis[i]+cost[i]排序,当前最先的第一个点能到的点的距离一定都是最近的,这些点在这之后都不会再被更新了。
这样只要维护一个并查集压缩路径,或者维护一个set存可能还会被更新的点就好了。
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<functional>
using namespace std;
typedef long long LL;
const LL maxn = 200010;
LL n, T, d[maxn], l[maxn], r[maxn], c[maxn], ans, sum, fa[maxn];
void read(LL &res)
{
char ch;
while ((ch = getchar())<'0' || ch>'9');
res = ch - '0';
while ((ch = getchar()) >= '0'&&ch <= '9') res = res * 10 + ch - '0';
}
void write(LL x)
{
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
struct cmp
{
bool operator()(const LL &a, const LL &b) const
{
return d[a] + c[a] > d[b] + c[b];
}
};
LL find(LL x)
{
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void merge(LL x, LL y)
{
x = find(x); y = find(y);
if (x == y) return;
fa[x] = y;
}
void find_dis(LL x)
{
d[x] = 0;
priority_queue<LL, vector<LL>, cmp> p;
p.push(x);
while (!p.empty())
{
LL q = p.top(), ll, rr; p.pop();
ll = q - r[q]; rr = q - l[q];
if (rr > 0)
for (LL j = max(ll, (LL)1);; j++)
{
j = find(j);
if (j > min(rr, n)) break;
if (d[j]>d[q] + c[q])
{
d[j] = d[q] + c[q];
p.push(j);
}
merge(j, j + 1);
}
ll = q + l[q]; rr = q + r[q];
if (ll <= n)
for (LL j = ll;; j++)
{
j = find(j);
if (j > min(rr, n)) break;
if (d[j]>d[q] + c[q])
{
d[j] = d[q] + c[q];
p.push(j);
}
merge(j, j + 1);
}
}
}
int main()
{
read(T);
while (T--)
{
read(n);
sum = 0;
for (int i = 1; i <= n; i++) read(l[i]);
for (int i = 1; i <= n; i++) read(r[i]);
for (int i = 1; i <= n; i++) read(c[i]), sum += c[i];
for (int i = 1; i <= n; i++) d[i] = sum + 1;
for (int i = 1; i <= n + 1; i++) fa[i] = i;
find_dis(1);
for (int i = 1; i <= n; i++)
{
if (i > 1) putchar(' ');
if (d[i] == sum + 1) putchar('-'), putchar('1');
else write(d[i]);
}
putchar(10);
}
return 0;
}