Man Down
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2428 Accepted Submission(s): 893
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).
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.
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
题目大意:
现在有N个板子,每个板子的高度已知,我们一开始会降落在最高的那个板子上,每一次下落都只能垂直下落。
我们的板子如果范围是【L,R】的话,我们下落的位子就是L或者是R,我们到每个板子上都会对应加血量或者减血量,血量没有上限,问最终能够获得的最大血量值,如果中途血量值小于等于0了,那么输出-1.
思路:
一开始肯定是要将所有板子从高到低排序的。
很显然我们可以将这个问题进行O(n^2)的一个暴力Dp,设定Dp【i】表示到达第i个板子上,最大获得的血量值。
但是考虑到数据范围的大小,我们显然不能直接Dp。
这里我们可以做一个线段树优化。
Dp【i】=Max(Dp【j】)(1<=j<i&&从j号板子可以降落到i号板子);
注意每一次只能垂直下落,所以我们线段树上第i个位子的值,是在某块板子的端点上,即将下落的最大值。
那么每一次我们要到达一个新的板子的时候,我们首先查询区间【L,R】内的最大值,如果不存在这样的下落点的话,这个板子就可以跳过了。
否则如果我们查到了区间最大值之后,我们再加上当前板子的价值。再更新点L和R的值为Dp【i】。同时我们要注意,因为我们Dp的过程选择了要到达这个板子,所以我们要将【L+1,R-1】的值都要重新置为0(或者负数都行);
过程维护一下即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
int h,l,r,val;
}a[150000];
int dp[150000];
int cmp(node a,node b)
{
if(a.h==b.h)return a.val>b.val;
else
return a.h>b.h;
}
/**********************/
#define N 100050
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int tree[150000*4];
int flag[150000*4];
void pushup(int rt)
{
tree[rt]=max(tree[rt*2],tree[rt*2+1]);
}
void pushdown(int l,int r,int rt)
{
if(flag[rt])
{
int m=(r+l)/2;
flag[rt*2]=flag[rt];
flag[rt*2+1]=flag[rt];
tree[rt*2]=flag[rt];
tree[rt*2+1]=flag[rt];
flag[rt]=0;
}
}
void build(int l,int r,int rt)
{
tree[rt]=flag[rt]=0;
if(l==r)
{
tree[rt]=0;
return ;
}
int m=(l+r)/2;
build(lson);build(rson);pushup(rt);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(l>=L&&r<=R)
{
tree[rt]=c;
flag[rt]=c;
return ;
}
pushdown(l,r,rt);
int m=(l+r)/2;
if(L<=m)
{
update(L,R,c,lson);
}
if(R>m)
{
update(L,R,c,rson);
}
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(l>=L&&r<=R)
{
return tree[rt];
}
int ans=0;
pushdown(l,r,rt);
int m=(l+r)/2;
if(L<=m)
{
ans=max(ans,query(L,R,lson));
}
if(R>m)
{
ans=max(ans,query(L,R,rson));
}
pushup(rt);
return ans;
}
/**********************/
int main()
{
int n;
while(~scanf("%d",&n))
{
int flag=0;
build(1,N,1);
for(int i=1;i<=n;i++)scanf("%d%d%d%d",&a[i].h,&a[i].l,&a[i].r,&a[i].val);
sort(a+1,a+1+n,cmp);
if(a[1].val+100<=0)
{
printf("-1\n");
continue;
}
for(int i=1;i<=n;i++)
{
if(i==1)
{
update(a[i].l,a[i].l,a[i].val+100,1,N,1);
update(a[i].r,a[i].r,a[i].val+100,1,N,1);
}
else
{
if(query(a[i].l,a[i].r,1,N,1)<=0)continue;
dp[i]=query(a[i].l,a[i].r,1,N,1)+a[i].val;
if(a[i].r-a[i].l>=2)update(a[i].l+1,a[i].r-1,-1,1,N,1);
update(a[i].l,a[i].l,dp[i],1,N,1);
update(a[i].r,a[i].r,dp[i],1,N,1);
}
}
int ans=query(1,N,1,N,1);
if(ans<=0||flag==1)printf("-1\n");
else printf("%d\n",ans);
}
}