正题
题目大意
nnn个数n−1n-1n−1个+++或−-−号的一个算式,加上一些括号使得运算结果最大。
解题思路
对于+++号左右的两个数字,无论如何加括号都不会变结果,所以我们可以合并这些数。然后就只剩下了减号,此时除了第一个就可以随意选择一段区间取反,那么对于嵌套了三层的括号,就可以拆成两层也就是最多只能嵌套两层括号。考虑dpdpdp,设fi,jf_{i,j}fi,j表示到第iii个,嵌套了jjj层的括号的情况下最大的答案。
时间复杂度O(n)O(n)O(n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10;
ll T,n,a[N],f[N][3],ans;
inline ll read()
{ll s=0,f=1; char c=getchar();while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9') {s=s*10+c-'0';c=getchar();}return s*f;
}
int main()
{
// freopen("jerry.in","r",stdin);
// freopen("jerry.out","w",stdout);scanf("%lld",&T);f[0][1]=f[0][2]=-1e18;while(T--){scanf("%lld",&n);for(int i=1;i<=n;i++)a[i]=read();ans=-1e18;for(ll i=1;i<=n;i++){if(a[i]<0){f[i][0]=-1e18;f[i][1]=max(f[i-1][1],max(f[i-1][0],f[i-1][2]))+a[i];f[i][2]=max(f[i-1][2],f[i-1][1])-a[i];}else{f[i][0]=max(f[i-1][0],max(f[i-1][1],f[i-1][2]))+a[i];f[i][1]=max(f[i-1][1]-a[i],f[i-1][2]-a[i]);f[i][2]=f[i-1][2]+a[i];}}printf("%lld\n",max(max(f[n][0],f[n][1]),f[n][2]));}
}