In Touch
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1876 Accepted Submission(s): 510
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++.
题意:n个点排在坐标轴1-n的位置,然后告诉你每个点能够访问的距离范围[l,r],
和他访问别的点的花费c[i],求从1出发访问每个点的最小花费。不能访问输出-1.
居然用一种看似会超时的方法过了这题难以置信。
用d[i]表示到i的最小花费,按照dij最短路思想,我们会用d[i]+cost [i]去试着更新
没有取到最小值的点。显然是用最小没有更新过其他点的d[i]+cost[j]去更新,所以
用优先队列维护没有更新过别的节点的节点,key值就是d[i]+cost[j]。然后线段树
维护区间d[i]值的最大,维护最大值的用意就是能够判断区间里面有没有存在能够
更新的节点。然后每个底层的节点最多被访问一次(访问到的时候它就已经取到
最小值了),复杂度看似是O(nlgn),其实可能有极端情况?
反正就这么就过了,貌似跑的还不算太慢。
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <set>
using namespace std;
#define maxn 211111
#define pl c<<1
#define pr (c<<1)|1
#define lson tree[c].l,tree[c].mid,pl
#define rson tree[c].mid+1,tree[c].r,pr
#define INF 1e15
struct node {
int l, r, mid;
long long Max;
}tree[maxn<<4];
int l[maxn], r[maxn];
long long cost[maxn], d[maxn];
int n;
void build_tree (int l, int r, int c) {
tree[c].l = l, tree[c].r = r, tree[c].mid = (l+r)>>1;
if (l == r) {
tree[c].Max = d[l];
return ;
}
build_tree (lson);
build_tree (rson);
tree[c].Max = max (tree[pl].Max, tree[pr].Max);
}
struct node1 {
int id;
long long num;
bool operator < (const node1 &a) const {
return num > a.num;
}
};
priority_queue <node1> gg;
void update (int l, int r, int c, int x, int y, long long val) {
if (val >= tree[c].Max)
return ;
if (l == r) {
tree[c].Max = val;
gg.push ((node1) {l, val+cost[l]});
d[l] = val;
return ;
}
if (tree[c].mid >= y) {
if (tree[pl].Max > val)
update (lson, x, y, val);
}
else if (tree[c].mid < x) {
if (tree[pr].Max > val)
update (rson, x, y, val);
}
else {
if (tree[pl].Max > val) update (lson, x, tree[c].mid, val);
if (tree[pr].Max > val) update (rson, tree[c].mid+1, y, val);
}
tree[c].Max = max (tree[pl].Max, tree[pr].Max);
}
void solve () {
for (int i = 2; i <= n; i++) d[i] = INF;
d[1] = 0;
build_tree (1, n, 1);
while (!gg.empty ()) {
gg.pop ();
}
gg.push ((node1) {1, cost[1]});
while (!gg.empty ()) {
node1 now = gg.top (); gg.pop ();
int u = now.id;
int x = u+l[u], y = u+r[u]; if (x == u) x++; y = min (y, n);
if (x <= y) {
update (1, n, 1, x, y, now.num);
}
x = u-r[u], y = u-l[u]; if (y == u) y--; x = max (1, x);
if (x <= y) {
update (1, n, 1, x, y, now.num);
}
}
for (int i = 1; i <= n; i++) {
if (d[i] >= INF) {
printf ("-1");
}
else
printf ("%lld", d[i]);
printf ("%c", (i == n ? '\n' : ' '));
}
}
int main () {
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%d", &n);
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", &cost[i]);
solve ();
}
return 0;
}