题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3016
题意:有n块木板,每一块木板有不同的高度h和左右端点的坐标xl和xr,从最高的木板下落,仅可以从木板的2个端点垂直下落,也就是当下落xi端点在下一块木板的[xl,xr]中才可以到达该木板,每一块木板有权值,初始值为100当初始值为0时死亡,问最好的情况到达地面(h=0)的时候权值最大
思路:一开始就往线段树去想因为是线段树专题嘛(我承认我看题解了)……但是本质上来说这是一道dp的题目,每到达一块木板有2种选择在左端点下落或者在右端点下落,但是如何得知下落之后的下一块木板了,由于数据量的问题,暴力处理的话会超时,这个时候就应该使用线段树来进行辅助优化,将木板由低到高进行排序,分别查询2个端点所在的区间被那一段线段所覆盖,则可以得知从该端点下落到达那一个木板,在用当前木板维护线段树就可以了。
因为dp的时候初始化为0,所以当权值为负数不需要在进行处理,并不是允许下落的时候出现权值为负数的情况。
在这里再阐述一下我对线段树的理解,它作为一种数据结构,是以一定的逻辑结构来保存处理数据,而不是作为一种算法提供输入端口输出端口吐出处理结果,像区间更新一类的操作线段树可以很好的辅助完成
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100030
using namespace std;
struct Tree
{
int l,r,date;
}tree[maxn*3];
struct Node
{
int l,r,h,val,lnxt,rnxt;
}s[maxn];
int lazy[maxn*3],dp[maxn];
bool cmp(Node p,Node q)
{
return p.h<q.h;
}
void Pushdown(int root)
{
if (lazy[root]!=-1)
{
lazy[root<<1]=lazy[root];
lazy[root<<1|1]=lazy[root];
tree[root<<1].date=tree[root].date;
tree[root<<1|1].date=tree[root].date;
lazy[root]=-1;
}
}
void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
tree[root].date=-1;
if (l==r) return;
int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
}
void update(int root,int l,int r,int val)
{
if (tree[root].l>=l && tree[root].r<=r)
{
lazy[root]=val;
tree[root].date=val;
return;
}
Pushdown(root);
int mid=(tree[root].l+tree[root].r)>>1;//cout<<root<<":"<<mid<<":"<<r<<endl;
if (l<=mid) update(root<<1,l,r,val);
if (r>mid) update(root<<1|1,l,r,val);
}
int que(int root,int gold)
{
if (tree[root].l==tree[root].r) return tree[root].date;
Pushdown(root);
int mid=(tree[root].l+tree[root].r)>>1;
if (gold<=mid) return que(root<<1,gold);
else if (gold>mid) return que(root<<1|1,gold);
}
void init()
{
memset(lazy,-1,sizeof(lazy));
memset(dp,0,sizeof(dp));
build(1,1,maxn);
s[0].l=1;
s[0].r=maxn;
s[0].h=0;
s[0].val=0;
}
int main()
{
int n;
while (scanf("%d",&n)!=EOF)
{
init();
for (int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&s[i].h,&s[i].l,&s[i].r,&s[i].val);
}
sort(s,s+n+1,cmp);
for (int i=0;i<=n;i++)
{
s[i].lnxt=que(1,s[i].l);
s[i].rnxt=que(1,s[i].r);
update(1,s[i].l,s[i].r,i);
}
dp[n]=100+s[n].val;
for (int i=n;i>=0;i--)
{
int ll=s[i].lnxt,rr=s[i].rnxt;
dp[ll]=max(dp[ll],dp[i]+s[ll].val);
dp[rr]=max(dp[rr],dp[i]+s[rr].val);
}
if (dp[0]<=0) printf("-1\n");
else printf("%d\n",dp[0]);
}
}