hdu3016——Man Down

Man Down

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1740    Accepted Submission(s): 626

Problem Description

The Game “Man Down 100 floors” is an famous and interesting game.You can enjoy the game from

http://hi.baidu.com/abcdxyzk/blog/item/16398781b4f2a5d1bd3e1eed.html

We take a simplified version of this game. We have only two kinds of planks. One kind of the planks contains food and the other one contains nails. And if the man falls on the plank which contains food his energy will increase but if he falls on the plank which
contains nails his energy will decrease. The man can only fall down vertically .We assume that the energy he can increase is unlimited and no borders exist on the left and the right.

First the man has total energy 100 and stands on the topmost plank of all. Then he can choose to go left or right to fall down. If he falls down from the position (Xi,Yi),he will fall onto the nearest plank which satisfies (xl <= xi <= xr)(xl is the leftmost
position of the plank and xr is the rightmost).If no planks satisfies that, the man will fall onto the floor and he finishes his mission. But if the man’s energy is below or equal to 0 , he will die and the game is Over.

Now give you the height and position of all planks. And ask you whether the man can falls onto the floor successfully. If he can, try to calculate the maximum energy he can own when he is on the floor.(Assuming that the floor is infinite and its height is 0,and
all the planks are located at different height).

Input

There are multiple test cases.

For each test case, The first line contains one integer N (2 <= N <= 100,000) representing the number of planks.

Then following N lines representing N planks, each line contain 4 integers (h,xl,xr,value)(h > 0, 0 < xl < xr < 100,000, -1000 <= value <= 1000), h represents the plank’s height, xl is the leftmost position of the plank and xr is the rightmost position. Value
represents the energy the man will increase by( if value > 0) or decrease by( if value < 0) when he falls onto this plank.

Output

If the man can falls onto the floor successfully just output the maximum energy he can own when he is on the floor. But if the man can not fall down onto the floor anyway ,just output “-1”(not including the quote)

Sample Input

4
10 5 10 10
5 3 6 -100
4 7 11 20
2 2 1000 10

Sample Output

140

Source

2009 Multi-University Training Contest 12 - Host by FZU

Recommend

gaojie   |   We have carefully selected several similar problems for you:  1542 1828 1540 2871 1698

一开始的写法超时了,然后用线段树优化了下, 转移的复杂度降到了O(logn),总复杂度是O(n * logn)

#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000, 102400000")

using namespace std;

const int N = 100010;
const int inf = 0x3f3f3f3f;

int dp[N][2];
int n;
struct node
{
	int l, r;
	int h;
	int w;
}blank[N];

struct node2
{
	int l, r;
	int h;
	int col;
}tree[N << 2];

int cmp(node a, node b)
{
	return a.h > b.h;
}

void build(int p, int l, int r)
{
	tree[p].l = l;
	tree[p].r = r;
	tree[p].col = -1;
	if (l == r)
	{
		return;
	}
	int mid = (l + r) >> 1;
	build(p << 1, l, mid);
	build(p << 1 | 1, mid + 1, r);
}

void update(int p, int l, int r, int val)
{
	if (l <= tree[p].l && tree[p].r <= r)
	{
		tree[p].col = val;
		return;
	}
	if (tree[p].col != -1)
	{
		tree[p << 1].col = tree[p].col;
		tree[p << 1 | 1].col = tree[p].col;
		tree[p].col = -1;
	}
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (r <= mid)
	{
		update(p << 1, l, r, val);
	}
	else if (l > mid)
	{
		update(p << 1 | 1, l, r, val);
	}
	else
	{
		update(p << 1, l, mid, val);
		update(p << 1 | 1, mid + 1, r, val);
	}
}

int query(int p, int pos)
{
	if (tree[p].l == tree[p].r)
	{
		return tree[p].col;
	}
	if (tree[p].col != -1)
	{
		tree[p << 1].col = tree[p].col;
		tree[p << 1 | 1].col = tree[p].col;
		tree[p].col = -1;
	}
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (pos <= mid)
	{
		return query(p << 1, pos);
	}
	else
	{
		return query(p << 1 | 1, pos);
	}
}

int main()
{
	while(~scanf("%d", &n))
	{
		memset (dp, -1, sizeof(dp));
		int left = inf, right = -inf;
		for (int i = 0; i < n; ++i)
		{
			scanf("%d%d%d%d", &blank[i].h, &blank[i].l, &blank[i].r, &blank[i].w);
			left = min(left, blank[i].l);
			right = max(right, blank[i].r);
		}
		// printf("%d %d\n", left, right);
		build(1, left, right);
		sort (blank, blank + n, cmp);
		for (int i = n - 1; i >= 0; --i)
		{
			int j = query(1, blank[i].l);
			if (j != -1)
			{
				dp[i][0] = max(dp[j][0], dp[j][1]) + blank[j].w;
			}
			else
			{
				dp[i][0] = 0;
			}
			j = query(1, blank[i].r);
			if (j != -1)
			{
				dp[i][1] = max(dp[j][0], dp[j][1]) + blank[j].w;
			}
			else
			{
				dp[i][1] = 0;
			}
			update(1, blank[i].l, blank[i].r, i);
		}
		int ans = max(dp[0][0], dp[0][1]) + 100 + blank[0].w;
		if (ans <= 0)
		{
			ans = -1;
		}
		printf("%d\n", ans);
	}
	return 0;
}
时间: 2024-12-20 05:56:40

hdu3016——Man Down的相关文章

HDU3016 Man Down 题解

HDU3016 Man Down] 线段树例题解析合集 题意:在平面内有n条横放的线段,每条线段给出高度.左右端点位置和能量(可正可负),最初处于最高的一条线段上且拥有100点能量和当前线段上的能量之和,每次可以从线段左边或右边竖直落下(可能落到其他线段上也可能落到地上),落到其他线段上则获得线段上能量并继续游戏,若落到地上则终止游戏,得分为当前能量之和.但任意一个时刻能量必须为正,当能量<=0时就失败了,终止游戏.若能落到地上,输出最大得分,若不能输出-1 这题我的方法比较奇特(傻) 假设地面

线段树题目总结

一.单点更新 1.hdu1166 敌兵布阵:有N个兵营,每个兵营都给出了人数ai(下标从1开始),有四种命令,(1)"Addij",表示第i个营地增加j人.(2)"Sub i j",表示第i个营地减少j人.(3)"Query ij",查询第i个营地到第j个营地的总人数.(4)"End",表示命令结束.解题报告Here. 2.hdu1754 I Hate It:给你N个数,M个操作,操作分两类.(1)"QAB"

数据结构---线段树

线段树 转载请注明出处,谢谢!http://blog.csdn.net/metalseed/article/details/8039326  持续更新中···   一:线段树基本概念 1:概述 线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN)! 性质:父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线段树

(转载)线段树模板(来自胡浩大牛)

http://www.notonlysuccess.com/(今天看二叉树,想回来看看,发现大牛博客进不去...) 如果要学,就要好好学.我copy的,如有错,请看http://www.cnblogs.com/Mu-Tou/archive/2011/08/11/2134427.html [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时觉得挺自豪的,还去pku打广告,但是现在我自己都不太好意思去看那篇文章了,觉得当时的代码风格实在是太丑了,很多线段树的初学者

线段树总结 (转载 里面有扫描线类 还有NotOnlySuccess线段树大神的地址)

转载自:http://blog.csdn.net/shiqi_614/article/details/8228102 之前做了些线段树相关的题目,开学一段时间后,想着把它整理下,完成了大牛NotOnlySuccess的博文“完全版线段树”里的大部分题目,其博文地址Here,然后也加入了自己做过的一些题目.整理时,更新了之前的代码风格,不过旧的代码仍然保留着. 同样分成四类,不好归到前四类的都分到了其他.树状数组能做,线段树都能做(如果是内存限制例外),所以也有些树状数组的题目,会标示出来,并且放

线段树——转

  一:线段树基本概念 1:概述 线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN)! 性质:父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线段树需要的空间为数组大小的四倍 2:基本操作(demo用的是查询区间最小值) 线段树的主要操作有: (1):线段树的构造 void build(int node,

线段树(转)

线段树   转载请注明出处,谢谢!http://blog.csdn.net/metalseed/article/details/8039326  持续更新中···   一:线段树基本概念 1:概述 线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN)! 性质:父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线