题解 滑稽树前做游戏,滑稽树后做交易 trade

题目名称我就不吐槽了。。。

题目描述

滑稽树前做游戏,滑稽树后做交易

(trade.cpp,3000ms,1024MB)

题目描述

滑稽果被排成一列,poison 的 lsr 要求每个顾客只能买一段连续的区间。

sxd 来这里买滑稽果,他对每个滑稽果都有一个喜爱程度 Ai 是一个整数,-100≤Ai≤100,

并保证∑Ai <=2147483647,最终的满意度为所有他买到的滑稽果的喜欢程度之和,如果和

为正(不管是正多少,只要大于 0 即可),则他满意了。

现在 sxd 想知道在他满意的条件下最多能买到多少滑稽果。

输入描述

第一行一个正整数 n,表示 lsr 一共摘了 n 个滑稽果。

第二行 n 个整数,每个整数 Ai 表示 sxd 第 i 个滑稽果的喜爱程度为多少。

输出描述

一行一个正整数 ans 表示在 sxd 满意的条件下最多能买到多少滑稽果

输入样例
5
0 0 -7 -6 1
输出样例
1
数据范围及提示

对于 30%的数据,n<=5*10^3

对于 60%的数据,n<=10^5

对于所有数据,n<=3*10^7

请注意本题的内存限制,完成代码后请务必计算一下你程序的内存是否超限。

由于本题的输入过大,请必须使用基于 fread 的输入模板,见题目目录下的 fastIO.cpp

题解

区间伸缩(尺取法)

代码

ver.0

#include <cstdio>
#include <algorithm>
#include <cctype>

using std::max;
using std::min;

const int N=30000000;
int a[N],sum[N+1],s[N+1];

inline char gc()
{
    static char buf[1<<12],*p1=buf,*p2=buf;
    return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<12,stdin),p1==p2)?EOF:*p1++;
}

#define dd c = gc()
inline int read()
{
    static int x;
    x = 0;
    int dd;
    bool f = false;
    for(; !isdigit(c); dd)
        if(c == '-')
            f = true;
    for(; isdigit(c); dd)
        x = (x<<1) + (x<<3) + (c^48);
    if(f)
        x = -x;
    return x;
}
#undef dd

int main()
{
    freopen("trade.in","r",stdin);
    freopen("trade.out","w",stdout);
    int n,ans=0,r=0;
    n=read();
    for (int i=0;i<n;++i) a[i]=read();
    for (int i=n-1;~i;--i)
    {
        sum[i]=sum[i+1]+a[i];
        s[i]=min(sum[i],s[i+1]);//s[n]=0,代表取从i开始取全部,需要更新
    }
    for (int i=0;i<n;++i)
    {
        r=max(r,i+1);
        while (r<=n&&s[r]<sum[i])//到n为止,代表取从i开始取全部,需要更新
        {
            ans=max(ans,r-i);
            ++r;
        }
        if (r==n) break; 
    }
    printf("%d",ans);
    return 0;
}

ver.1 优化

#include <cctype>
#include <cstdio>

const int N = 30000000;
int sum[N + 1], s[N + 1];

inline char gc()
{
    static char buf[1 << 24], *p1 = buf, *p2 = buf;
    return (p1 == p2) && (p2 = (p1 = buf) + fread(buf, 1, 1 << 24, stdin), p1 == p2) ? EOF : *p1++;
}

#define dd c = gc()
inline int read()
{
    static int x;
    x = 0;
    int dd;
    bool f = false;
    for (; !isdigit(c); dd)
        if (c == '-')
            f = true;
    for (; isdigit(c); dd)
        x = (x << 1) + (x << 3) + (c ^ 48);
    return f ? -x : x;
}
#undef dd

inline int max(int x, int y)
{
    return x > y ? x : y;
}

int main()
{
    freopen("trade.in", "r", stdin);
    freopen("trade.out", "w", stdout);
    int n, ans = 0, r = 1;
    n = read();
    sum[0] = read();
    for (int i = 1; i < n; ++i)
        sum[i] = sum[i - 1] + read();
    s[n - 1] = sum[n - 1];
    for (int i = n - 2; ~i; --i)
        s[i] = max(sum[i], s[i + 1]);
    for (int i = 0; i < n && r < n; ++i, ++r)
    {
        if (n - i <= ans)
            break;
        if (s[r] <= sum[i])
            continue;
        while (r <= n && s[r] > sum[i])
            ++r;
        ans = r - 1 - i;
    }
    printf("%d", ans);
    return 0;
}

转载于:https://www.cnblogs.com/mxdh/p/10387705.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值