HDU 3016 Man Down

来源:互联网 发布:mysql join 编辑:程序博客网 时间:2024/06/06 02:00

题目链接: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 100030using 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]);    }}


0 0
原创粉丝点击