关闭

HDU 5361 (优先队列 线段树)

255人阅读 评论(0) 收藏 举报
分类:

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 (1in)
 

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 (1n2×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(0lirin,1ci109)
 

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 -1
Hint
If 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;
}

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:93269次
    • 积分:5367
    • 等级:
    • 排名:第5029名
    • 原创:463篇
    • 转载:0篇
    • 译文:0篇
    • 评论:12条
    最新评论