zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    登录注册数据库建立
    AngularJS学习小结
    响应布局
    JQuery内容从左边框移到右边框
    Jquery图片轮播和CSS图片轮播
    Bootstrap栅格系统
    用Javascript大批量收集网站数据
    如何用CSS快速布局(一)—— 布局元素详细
    怎么应用vertical-align,才能生效?
    line-height系列(二)——对行内元素(文字、图片、兄弟元素)、块级元素设置line-height后的表现
  • 原文地址:https://www.cnblogs.com/nanke/p/3002496.html
Copyright © 2011-2022 走看看