zoukankan      html  css  js  c++  java
  • hdu 3016(线段树 + DP)

    题意:一个游戏(做题前可以先玩一下帮助理解)。题意比游戏简易:每个木板都有一个权值,可正可负或0,人在上面,自身能量要加上这个权值(即能量会发生增减)。人一开始有100能量,站在最高的木板上(要加上这个能量的权,所以其实起始能量应该为100+该板能量)。然后人往下跳,跳法有讲究并不像真实游戏那样可以移动,人下落,只能从一块木板的端点垂直下落,中途不能移动,这和实际游戏有区别,但是也使问题简化了。问这个人怎么跳,使在它落到地面的时候,能量最大,如果中途或者到地面能量<=0,或者跳到一个木板上,下面没有木板可以接住自己了,那么游戏结束,输出-1

    分析:

    既然只能垂直下落,而且是落在最近的板上,所以其实下落后处于哪个木板是唯一确定的
    (这里指的唯一确定是当从左端点下落是唯一确定,从右端点下落是唯一,所以从一个木板下落就两种可能)
    另外,这个问题本质是个DP,其实是可以直接DP的,就是从顶部走到底部的一个策略,因为从一个木板走到下面,选择是唯一
    这个DP就很容易想了,可以把每个木板看做一个点,移动看作一条有向边,那么就构成一个有向图,而且是个DAG,要使下落到地面时的能量最高
    就是在这个DAG上找一个最长路。
    但是建图是个问题,点数又太多,而且鉴于这题,没必要显式建图,只要能知道每个木板能移向哪些木板即可
    这题的线段树有什么用处(我们老是做题,知道这题被归为线段树,就死命往线段树想,其实到底为什么是线段树都不知道,就算想出来,也没意思)
    线段树就是用于解决上面的问题,快速确定每个木板可以向那些木板移动
    以当前木板的做端点X为例,从x垂直下落,满足的木板为 XL<=X<=XR ,并且是最接近当前木板的那块
    我们可以换一下思维,看做点X被覆盖了,X是被[XL,XR]覆盖(当然它除了覆盖X还覆盖了很多其他点),那么我们可以换成单点查询
    查询X的时候,发现X被覆盖了,而且是被[XL,XR]这个线段覆盖的,那么我们就返回它是哪条线段即可
    但还有个问题,点X可能不止被一个线段覆盖,而是被多个线段覆盖,那么该选哪个呢?其实这就是我们的最近问题,它下落是落在离他最近的木板上的
    所以虽然X被多个线段覆盖,我们只能要最近的那个,怎么确定最近那个呢?那就是将木板按高度升序排序
    从最矮的木板开始,让它去覆盖它对应的区间,那么从低到高,点X就一定是被最高的而且满足的木板覆盖的
    而且用当前木板去覆盖之前,先查询从它左边或者右边掉下去能到那个木板

    //#pragma comment(linker, "/STACK:102400000")
    #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<list>
    #include<queue>
    #include<stack>
    #include<vector>
    #define tree int o,int l,int r
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define lo o<<1
    #define ro o<<1|1
    #define pb push_back
    #define mp make_pair
    #define ULL unsigned long long
    #define LL long long
    #define inf 0x7fffffff
    #define eps 1e-7
    #define N 100009
    #define M 100000
    using namespace std;
    int m,n,T,t,ql,qr;
    struct Node
    {
        int h,l,r,val;
        int ll,rr;
        bool operator <(const Node &a)const
        {
            return h<a.h;
        }
    }node[N];
    int d[N];
    int sum[N<<2];
    void pushdown(int o)
    {
        if(sum[o]!=-1)
        {
            sum[lo]=sum[ro]=sum[o];
            sum[o]=-1;
        }
    }
    void update(tree,int k)
    {
        if(ql<=l&&qr>=r)
        sum[o]=k;
        else
        {
            pushdown(o);
            int mid=(l+r)>>1;
            if(ql<=mid)update(lson,k);
            if(qr>mid)update(rson,k);
        }
    }
    int query(tree,int pos)
    {
        if(sum[o]!=-1)
        return sum[o];
        int mid=(l+r)>>1;
        if(pos<=mid)
        return query(lson,pos);
        return query(rson,pos);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("ex.in","r",stdin);
    #endif
        while(scanf("%d%*c",&n)==1)
        {
            node[0]=(Node){0,1,100000,0};
            for (int i=1;i<=n;++i )
                scanf("%d%d%d%d",&node[i].h,&node[i].l,&node[i].r,&node[i].val);
            n++;
            sort(node,node+n);
            memset(d,-1,sizeof(d));
            sum[1]=0;
            for (int i=1;i<n;++i )
            {
                node[i].ll=query(1,1,M,node[i].l);
                node[i].rr=query(1,1,M,node[i].r);
                ql=node[i].l;
                qr=node[i].r;
                update(1,1,M,i);
            }
            d[n-1]=100+node[n-1].val;
            for(int i=n-1;i>0;i--)if(d[i]>0)
            {
                d[node[i].ll]=max(d[node[i].ll],d[i]+node[node[i].ll].val);
                d[node[i].rr]=max(d[node[i].rr],d[i]+node[node[i].rr].val);
            }
            printf("%d
    ",d[0]>0?d[0]:-1);
        }
        return 0;
    }
  • 相关阅读:
    centos7最小化安装无法tab补全
    rhcsa备战笔记
    idea springboot应用启动
    idea 导入Mapper错误报错设置
    idea 忽略显示文件
    maven 插件jetty/tomcat启动 web 应用
    maven jstl、jsp、servlet依赖
    maven 项目目录图与web 应用结构图对比
    maven 远程仓库、私服及镜像配置
    maven windows环境nexus3.0私服搭建
  • 原文地址:https://www.cnblogs.com/sbaof/p/3399495.html
Copyright © 2011-2022 走看看