hdu 3016 线段树+dp

用线段树由低到高覆盖每一层台阶的长度,根据线段左右两端连边,然后由高到底DP即可

#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn= 200001;
const int mincost=-200000000;
struct Pool
{
    int to,pre;
}pool[maxn<<1];
int p[maxn<<1],top,n;
int dp[maxn];
void addedge(int x,int y)
{
    pool[++top].to=y;
    pool[top].pre=p[x];
    p[x]=top;
}
struct datb
{
    int h,xl,xr,value;
    bool operator <(const datb &t)const
    {
        return h<t.h;
    }
}d[maxn];
int m[maxn<<2],lazy[maxn<<2];
bool defi[maxn<<2];
void pushdown(int rt)
{
    if(lazy[rt]!=-1)
    {
        m[rt]=lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
        defi[rt]=true,lazy[rt]=-1;
    }
}
void pushup(int rt)
{
    if(defi[rt<<1]==true&&defi[rt<<1|1]==true&&m[rt<<1]==m[rt<<1|1])
    {
        defi[rt]=true;
        m[rt]=m[rt<<1];
    }
    else
    {
        defi[rt]=false;
    }
}
void init()
{
    m[1]=0;
    defi[1]=true;
    lazy[1]=0;
    top=0;
    for(int i=0;i<=n;i++)
    {
        p[i]=0;
        dp[i]=mincost;
    }
}
void change(int rt,int l,int r,int x,int y,int s)
{
    if(x<=l&&y>=r)
    {
        m[rt]=s;
        lazy[rt]=s;
        defi[rt]=true;
        return ;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(mid>=x)
    change(rt<<1,l,mid,x,y,s);
    if(mid<y)
    change(rt<<1|1,mid+1,r,x,y,s);
    pushup(rt);
}
int find(int rt,int l,int r,int k)
{
    pushdown(rt);
    if(r>=k&&l<=k&&defi[rt]==true)
    return m[rt];
    int mid=(l+r)>>1;
    if(mid>=k)
    return find(rt<<1,l,mid,k);
    return find(rt<<1|1,mid+1,r,k);
}

int main()
{
    int t1,t2;
    while(scanf("%d",&n)!=EOF)
    {
        init();
        for(int i=1;i<=n;i++)
        scanf("%d%d%d%d",&d[i].h,&d[i].xl,&d[i].xr,&d[i].value);
        sort(d+1,d+1+n);
        top=0;
        for(int i=1;i<=n;i++)
        {
            t1=find(1,1,100000,d[i].xl);
            t2=find(1,1,100000,d[i].xr);
            //printf("%d %d\n",t1,t2);
            addedge(i,t1);
            addedge(i,t2);
            change(1,1,100000,d[i].xl,d[i].xr,i);
        }
        dp[n]=d[n].value+100;
        for(int i=n;i>=1;i--)
        {
            for(int j=p[i];j;j=pool[j].pre)
            {
                int t=pool[j].to;
                dp[t]=max(dp[t],dp[i]+d[t].value);
            }
        }
        if(dp[0]<=0)
        printf("-1\n");
        else
        printf("%d\n",dp[0]);
        /*for(int i=1;i<=n;i++)
        {
            printf("%d: ",d[i].h);
            for(int j=p[i];j;j=pool[j].pre)
            printf("%d ",pool[j].to);
            printf("\n");
        }*/
    }
}

 

posted @ 2013-08-07 17:06  acahesky  阅读(272)  评论(0编辑  收藏  举报