• zoj3381 Osaisen Choudai!


    题意:忽略题目背景,就是要收集最多的钱, 如果第i天拿到了si 的钱, 那么第i+x[i] 天 到 第i + y[i] - 1 天必须再拿一次,否则就再也拿不到钱了,当然,第i +x[i]天之前也是拿不到的, 题目要求第一天必须拿。。

    分析:一开始想到了用记忆化搜索,代码很短, 一下就敲完了, 结果也果断超时了

    后来想到了按记忆化搜索的思路,直接从最后一天开始算起,用dp[i] 表示第i天拿到了钱之后,到第n天为止,最多拿到的钱数,

     那么dp[i] = s[i] + max(dp[j])    (i + x[i] <= j <= i + y[i] - 1)

    到这一步就很明显了,这里涉及到了区间最值的问题,我们可以用线段树来维护

     

    zoj3381
    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    using namespace std;
    
    const int N = 50000 + 10;
    
    int dp[N];
    int s[N], x[N], y[N];
    int n;
    
    struct node
    {
        int l, r, maxx;
    }p[N * 3];
    
    void build(int s, int t, int k)
    {
        p[k].l = s, p[k].r = t;
        p[k].maxx = 0;
        if( s == t )
            return ;
        int kl = k << 1, kr = kl + 1, mid = (s + t) >> 1;
        build(s, mid, kl);
        build(mid + 1, t, kr);
    }
    
    void update(int k, int s, int val)
    {
        if(s == p[k].l && p[k].r == p[k].l)
        {
            p[k].maxx = val;
            return ;
        }
        int kl = k << 1, kr = kl + 1, mid = (p[k].l + p[k].r) >> 1;
        if( s <= mid ) update(kl, s, val);
        else update(kr, s, val);
        p[k].maxx = max(p[kl].maxx, p[kr].maxx);
    }
    
    
    int query(int s, int t, int k)
    {
        if( s <= p[k].l && t >= p[k].r)
        {
            return p[k].maxx;
        }
        int mid = (p[k].l + p[k].r) >> 1;
        int kl = k << 1, kr = kl + 1;
        int a = 0, b = 0;
        if(s <= mid) a = query(s, t, kl);
        if(t > mid) b = query(s, t, kr);
        return max(a, b);
    }
    
    
    int main()
    {
        while(scanf("%d",&n) == 1)
        {
            for(int i = 1; i <= n; ++i)
                scanf("%d %d %d",&s[i], &x[i], &y[i]);
            build(1, n, 1);
            update(1, n, s[n]);
            int ans = 0;
            for(int i = n - 1; i >= 1; --i)
            {
                int l = i + x[i];
                int r = i + y[i] - 1;
                r = min(r, n);
                int val = s[i] + query(l, r, 1);
                update(1, i, val);
                if(i == 1) ans = val;
            }
            printf("%d\n",ans);
            
        }
        return 0;
    }
  • 相关阅读:
    jQuery图片翻转弹出动画特效
    HTML5来了,7个混合式移动开发框架
    10款很好用的 jQuery 图片滚动插件
    JS图片自动和可控的轮播切换特效
    CSS3扇形动画菜单 鼠标滑过扇形展开动画
    css里面的几个你不知道的属性
    JS判断是否是微信打开页面
    js的escape()、encodeURI()、encodeURIComponent()区别详解
    使用HTML5的十大原因
    Hybrid App开发 四大主流移平台分析
  • 原文地址:https://www.cnblogs.com/nanke/p/3002496.html
Copyright © 2020-2023  润新知