jerry
题目描述
众所周知,Jerry 鼠是一只非常聪明的老鼠。
Jerry 聪明到它可以计算64 位有符号整形数字的加减法。
现在,Jerry 写下了一个只由非负整数和加减号组成的算式。它想给这个算式添加合法的括号,使得算式的结果最大。这里加减法的运算优先级相同,和我们在日常生活中接触到的一样,当没有括号时,先算左边的,再算右边的。
比如,算式 (1+2)+3-(4-5)+6(1+2)+3−(4−5)+6 是合法的,但是 )1+2()1+2( 和 (-)1+2(−)1+2 以及 (1)+2(1)+2 都是不合法的。
输入格式
接下来,共有 TT 组数据,每组的格式如下:
第一行一个整数 nn,代表数字的个数。
接下来一行共 2n-12n−1 个符号或非负整数,组成一个由空格隔开的算式。
输出格式
一行一个整数,代表添加括号后,算式最大的可能结果。
样例
样例输入1
1 3 5 - 1 - 3
样例输出1
7
样例1说明
5-(1-3) = 7
样例输入2
1 4 1 - 1 - 1 - 3
样例输出2
4
样例2说明
1- (1 - 1 - 3) = 4
样例3
下发了额外的一个大型样例文件。
数据范围与提示
测试点编号 | n的范围 | 特殊性质 |
---|---|---|
1 | n \le 3n≤3 | 无 |
2,3 | n \le 10n≤10 | T \le 10T≤10 |
4,5 | n \le 100n≤100 | T \le 100T≤100 |
6,7 | n \le 1000n≤1000 | T \le 100T≤100 |
8,9,10 | \sum {n} \le 2 \times 10^5∑n≤2×105 | 无 |
对于全部的数据, n \le 10^5 , \sum {n} \le 2 \times 10^5, 2 \le nn≤105,∑n≤2×105,2≤n,算式中出现的数字在 [0,10^9][0,109] 区间内。
来源
CSP-S 2019模拟 长沙一中2
Solution
令f[i][j]表示前i个数,前面有j个左括号的最大值。
在一个点可以加一个左括号,删一个左括号,或不改变。(删两个等价于不删,加两个...想啥呢)
那么就是n^2的了
题解告诉我只需要两层括号,于是就O(N)了
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define maxn 1000006 #define ll long long #define inf 1e16 #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; int T,n; ll f[maxn][3],a[maxn],g[maxn]; ll R(){ int F=1,v;char ch;_(!)if(ch=='-')F=0;v=(ch^48); _()v=(v<<1)+(v<<3)+(ch^48);return F?v:-v; } void work(){ n=R(); for(int i=1;i<=n;i++)a[i]=R(); for(int i=0;i<=n;i++) for(int j=0;j<=2;j++)f[i][j]=-inf; g[0]=1;for(int i=1;i<=n;i++)g[i]=-g[i-1]; f[0][0]=0; for(int i=1;i<=n;i++){ for(int j=0;j<=2;j++){ int v=g[j]*a[i]; if(j>0&&a[i-1]<0)f[i][j]=max(f[i][j],f[i-1][j-1]+g[j]*a[i]); f[i][j]=max(f[i][j],f[i-1][j]+g[j]*a[i]); if(j<2)f[i][j]=max(f[i][j],f[i-1][j+1]+g[j]*a[i]); } } ll ans=-inf; for(int x=0;x<=2;x++)ans=max(ans,f[n][x]); printf("%lld\n",ans); } int main(){ for(scanf("%d",&T);T--;work()); return 0; }