【GMOJ6804】模拟jerry
题目
题目链接:https://gmoj.net/senior/#main/show/6804
众所周知,Jerry 鼠是一只非常聪明的老鼠。Jerry 聪明到它可以计算 64 位有符号整形数字的加减法。现在,Jerry 写下了一个只由非负整数和加减号组成的算式。它想给这个算式添加合法的括号,使得算式的结果最大。这里加减法的运算优先级相同,和我们在日常生活中接触到的一样,当没有括号时,先算左边的,再算右边的。比如,算式 (1+2)+3−(4−5)+6 是合法的,但是 )1+2( 和 (−)1+2 以及 −(1)+2 都是不合法的。
思路
括号嵌套括号最多只会嵌套两层,因为嵌套三层之后等价于没有套。
发现只有在 - 后面加括号才会改变答案,所以我们固定在 + 后边一定不能加括号,设 \(f[i][j]\) 表示处理到第 \(i\) 个数字,在第 \(j\) 层括号的最大和。如果 \(j=1\) 需要变号。
分类当前符号简单转移即可。时间复杂度 \(O(n)\)。
思路
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
int Q,n,x;
ll f[N][3];
char ch[3];
int main()
{
freopen("jerry.in","r",stdin);
freopen("jerry.out","w",stdout);
scanf("%d",&Q);
while (Q--)
{
f[1][1]=f[1][2]=-1000000000000000000LL;
scanf("%d%lld",&n,&f[1][0]);
for (int i=1;i<n;i++)
{
scanf("%s%d",ch,&x);
if (ch[0]=='+')
{
f[i+1][0]=max(f[i][0]+x,f[i][1]-x);
f[i+1][1]=max(f[i][1]-x,f[i][2]+x);
f[i+1][2]=f[i][2]+x;
}
else
{
f[i+1][0]=max(f[i][0]-x,f[i][1]+x);
f[i+1][1]=max(f[i][0]-x,max(f[i][1]+x,f[i][2]-x));
f[i+1][2]=max(f[i][1]+x,f[i][2]-x);
}
}
printf("%lld\n",max(f[n][0],max(f[n][1],f[n][2])));
}
return 0;
}