题目链接:点击这里
题目大意:
多组输入,每组输入给出
n
n
n 块木板,木板高度为
h
h
h 左右边界分别为
l
,
r
l,r
l,r 其还有一个属性为
v
a
l
val
val,玩家初始有
100
100
100 滴血,玩家只能从当前木板的左右边界竖直向下跳,每跳到一块木板上玩家血量就会变化
v
a
l
val
val (val可能小于0) ,求从最上面的木板跳到地面玩家的最大生命值
题目分析:
首先我们要知道如何确定能从当前木板跳到哪个木板上,这个我们可以让高度从小到大用线段树做一次染色,代码中的
n
e
a
r
[
i
]
[
0
]
,
n
e
a
r
[
i
]
[
1
]
near[i][0],near[i][1]
near[i][0],near[i][1] 分别代表从
i
i
i 号木板的左右两边可以跳到的木板标号
知道这个以后我们就可以从上到下做一次
d
p
dp
dp :
设
d
p
[
i
]
dp[i]
dp[i] 为在高度为
i
i
i 的板子上最大的生命值,则有如下转移方程:
d
p
[
n
e
a
r
[
i
]
[
0
]
]
=
m
a
x
(
d
p
[
n
e
a
r
[
i
]
[
0
]
]
,
d
p
[
i
]
+
v
a
l
[
n
e
a
r
[
i
]
[
0
]
]
)
dp[near[i][0]] = max(dp[near[i][0]],dp[i]+val[near[i][0]])
dp[near[i][0]]=max(dp[near[i][0]],dp[i]+val[near[i][0]])
d
p
[
n
e
a
r
[
i
]
[
1
]
]
=
m
a
x
(
d
p
[
n
e
a
r
[
i
]
[
1
]
]
,
d
p
[
i
]
+
v
a
l
[
n
e
a
r
[
i
]
[
1
]
]
)
dp[near[i][1]] = max(dp[near[i][1]],dp[i]+val[near[i][1]])
dp[near[i][1]]=max(dp[near[i][1]],dp[i]+val[near[i][1]])
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
#define Inf 0x3f3f3f3f3f3f3f3f
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 3e5+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
struct node{
int l,r,h,val;
bool operator<(const node b)const
{
return h < b.h;
}
}nod[maxn];
struct sgt{
int val,lazy;
}a[maxn<<2];
int n,m,dp[maxn],near[maxn][2];
void pushdown(int root)
{
if(a[root].lazy)
{
int tmp = a[root].lazy;
a[root].lazy = 0;
a[root<<1].lazy = tmp;
a[root<<1|1].lazy = tmp;
a[root<<1].val = a[root<<1|1].val = tmp;
}
}
void build(int root,int l,int r)
{
if(l == r)
{
a[root].val = 0;
a[root].lazy = 0;
return ;
}
int mid = l+r>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
a[root].val = a[root].lazy = 0;
}
void updat(int root,int l,int r,int ql,int qr,int val)
{
if(l>qr || r<ql) return ;
if(l>=ql && r<=qr)
{
a[root].lazy = a[root].val = val;
return ;
}
int mid = l+r>>1;
pushdown(root);
updat(root<<1,l,mid,ql,qr,val);
updat(root<<1|1,mid+1,r,ql,qr,val);
}
ll query(int root,int l,int r,int pos)
{
if(l == r) return a[root].val;
int mid = l+r>>1;
pushdown(root);
if(pos <= mid) return query(root<<1,l,mid,pos);
else return query(root<<1|1,mid+1,r,pos);
}
int main()
{
while(~scanf("%lld",&n))
{
memset(dp,0,sizeof(dp));
int maxx = 0;
for(int i = 1;i <= n;i++)
{
nod[i].h = read();nod[i].l = read(),nod[i].r = read();nod[i].val = read();
maxx = max(maxx,nod[i].r);
}
build(1,1,maxx);
sort(nod+1,nod+n+1);
for(int i = 1;i <= n;i++)
{
near[i][0] = query(1,1,maxx,nod[i].l);
near[i][1] = query(1,1,maxx,nod[i].r);
updat(1,1,maxx,nod[i].l,nod[i].r,i);
}
dp[n] = 100+nod[n].val;
for(int i = n;i;i--)
{
if(dp[i] <= 0) continue;
dp[near[i][0]] = max(dp[near[i][0]],dp[i]+nod[near[i][0]].val);
dp[near[i][1]] = max(dp[near[i][1]],dp[i]+nod[near[i][1]].val);
}
if(dp[n] > 0) printf("%d\n",dp[0]);
else puts("-1");
}
return 0;
}