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);
}