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

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

离散化+线段树 poj2528

//离散化+线段树 #include #include #include #define CLR(A) memset(A,0,sizeof(A)) using namespace std; ...

Hdu 1394 Minimum Inversion Number(线段树或树状数组)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java...

HDU - 4302 :Holedox Eating ,线段树、树状数组+二分,优先队列

Description Holedox is a small animal which can be considered as one point. It lives in a straigh...

hdu 4006 The kth great number(线段树 || 优先队列)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4006 求一个数字序列的第K大的值。先输入两个数字n,k,接着是n行输入,I表示加入新的数字,Q是询问第k大...

hdu 4006 The kth great number 线段树/优先队列/set

题目意思:     有n种操作,I代表插入数据,q代表输出第k大的数。 区间的大数据的操作,基本是用树操作。 这到题目可以用三种方法来做。 (1) 线段树 考虑到题目可能有负数,给每...

hdu 2430 优先队列/线段树

1.我自己的想法是用线段树的 考虑从i开头的字串,设sum[i,n] = x,sum[j,n] = y; 要使得x mod p + y mod p 只要用线段树处理每个y的最小sum,就可以在log...

HDU 5361 In Touch (优先队列+并查集优化)

题意:求源点到所有点的最短距离。每个点只能到达与它相距l到r之间的点,且这个点到达这些点的花费都为c。 思路:这道题和普通最短路的区别是这个图有可能是个极为稠密的图,那么对于dijkstra算法来说时...

In Touch (hdu 5361 优先队列的Dij + 并查集优化)

题意:有n个点站成一排,相邻距离为1,每个点 i 可以联系上距离自己 x 的点并且花费Ci,其中Li...

HDOJ 4302 —— 线段树 或 优先队列

Holedox Eating Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...
  • zkzxmzk
  • zkzxmzk
  • 2013年10月01日 17:39
  • 746

HDOJ 5360 优先队列&简单线段树

题意 邀请n个人去玩,每个人接受邀请的条件是当前已接受邀请的人数m >= li && m 思路 这里给两个思路吧。。。比赛时想了个线段树的思路,写起来麻烦些,结果0写成了1,T掉了,还以为是复杂度估...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 5361 (优先队列 线段树)
举报原因:
原因补充:

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