[JZOJ5523] +/-

Description

世界的最终法则是一条式子。
这条式子很简单,形如”A[1] op[1] A[2] op[2] … op[n-1] A[n]”,其中A[i]为正整数,op[i]为+或-。
现在为了使世界达到一个前所未有的发展高峰,需要在式子里加入若干对括号,使得式子最后运算的得出的结果最大化,加入一对括号时,左括号只能加在数字前,右括号只能加在数字后,且左括号必须在右括号前。
现在给你n,A[1..n]以及op[1..n-1],让你求出式子运算结果的最大值。
对于100%的数据,1<=n<=100000,1<=A[i]<=10^9

Solution

这种题一般都是贪心

首先左括号一定在符号后,否则就没有用

有结论:括号最多只会嵌套两层,大于等于三层的情况都可以拆成两层以下
很容易发现这是对的

又有结论:
假设是当前是这样一段- + + - + - +

那么从第二个负号开始,可以把后面全部弄成正的(一个负号带一段正号)
负贡献只有前面第一个负和后面一段正

那么枚举从哪一个负号为开头做上面的东西,这个负号前面都是原来的答案,后面的按照上面处理

可以搞个前缀和之类的东西做到O(N)

Code

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 100005
#define LL long long
using namespace std;
LL a[N],op[N],f[N];
int n;
int main()
{
    cin>>n;
    op[1]=1;
    scanf("%d",&a[1]);
    fo(i,2,n)
    {
        char ch;
        scanf(" %c %d",&ch,&a[i]);
        if(ch=='+') op[i]=1;
        else op[i]=-1;
    }
    fo(i,1,n) f[i]=f[i-1]+op[i]*a[i];
    LL s=0,s1=0,ans=-1e15;
    fod(i,n,2)
    {
        if(op[i]<0) 
        {
            ans=max(ans,f[i]-s1+s);
            s+=a[i]+s1;
            s1=0;
        }
        else s1+=a[i];
    }
    printf("%lld\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值