HDU 5361 (优先队列 线段树)

原创 2016年05月31日 22:07:57

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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU5361 In Touch(线段树 + 最短路)

传送门 恰逢才做过VFK的A+B Problem,发现这道题也可以那样搞。区间连边的时候,我们就可以给那个区间在线段树对应的标号上连边。 线段树也可以不建出来,直接当做一个标号的合集,不占用内存,...
  • geng4512
  • geng4512
  • 2016年02月24日 12:56
  • 540

HDU 5361 In Touch

Problem Description There are n soda living in a straight line. soda are numbered by 1,2,…,n from...
  • jtjy568805874
  • jtjy568805874
  • 2015年08月07日 17:07
  • 634

HDU5361 In Touch(最短路 + 线段树)

/** 题意:一条n个点,第i个点可以到达[i - Ri, i - Li], [i + Li, i + Ri]的任意一个点,花费为Ci,问第1个点 到其他各点的最小花费 思路:Dijkstra + ...
  • hnust_Derker
  • hnust_Derker
  • 2018年02月21日 16:52
  • 20

HDU 5361 最短路变形

点击打开链接 题意:给了n个点排成一行,每两个距离为1,然后对于每个点来说它有个L和R,意思是距离在L到R中间的所有点它都能到达,费用是C,问从小出发的单源所有的点的距离 思路:看了网上神犇的题解...
  • Dan__ge
  • Dan__ge
  • 2016年07月07日 20:05
  • 1341

hdu5361(最短路+并查集)

链接:点击打开链接 题意:有n个点排成一排,编号从1到n,每个点可以到自己[l, r]距离的位置,花费c,问一号店到其他点的最小花费 代码:#pragma comment(linker, "/ST...
  • stay_accept
  • stay_accept
  • 2016年07月07日 21:14
  • 336

hdu 5361 2015多校联合训练赛#6 最短路

In Touch Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total...
  • firenet1
  • firenet1
  • 2015年08月06日 18:36
  • 1619

HDU 5361 In Touch

首先的想法是线段树,因为是区间更新的,所以就是一边dij一边query和update。 今天想了一想,觉得似乎不要用这么麻烦的方法。 下面证明通过某种排序方式使得每个点只要被更新过了,就必定是最近...
  • u013007900
  • u013007900
  • 2015年08月07日 14:04
  • 760

HDU5361 In Touch

题目描述:In Touch Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)...
  • u013625492
  • u013625492
  • 2015年09月24日 14:45
  • 156

线段树优化连边,Dijkstra(In Touch,HDU 5361)

第二次被vector卡空间。。。但凡用到了vector,空间复杂度就别想算对了。。。以后少用vector,多用链式前向星。(特别是空间比较紧的时候) 还有一些实现上的失误, a=max(1,i-...
  • xl2015190026
  • xl2015190026
  • 2017年07月10日 21:37
  • 120

HDU 5361 In Touch (2015 多校6 1009 最短路 + 区间更新)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5361题意:最短路,求源点到所有点的最短距离。但与普通最短路不同的是,给出的边是某点到区间[l,r]内任意点...
  • u014357885
  • u014357885
  • 2015年08月07日 11:01
  • 741
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 5361 (优先队列 线段树)
举报原因:
原因补充:

(最多只允许输入30个字)