- 首先可以将所有相邻的正数合并在一起, 不影响答案, 且会使得数列具有性质 : 加号之后一定是减号 .
- 还有个非常重要的性质 : 若两个 负号 同时出现在一起, 则除第一个负号后的数字, 后面的所有数字均可取到正值 .
考虑从后往前去决定每个数前加不加括号,
- , 括号对其无影响,
- ,
- , 根据性质, .
- , 根据性质, 有两个决策, 分别是
- 不加括号得到,
- 加括号失去但得到后所有数字的和;
得到
- 多组数据, 初值 ,
- 注意 处理时需要对 加绝对值 .
- 函数会炸 .
#include<bits/stdc++.h>
#define reg register
typedef long long ll;
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 2e5 + 10;
int N;
int cnt;
int A[maxn];
ll B[maxn];
ll F[maxn];
ll suf_sum[maxn];
char opt[3];
ll abd(ll x){ return x>0?x:-x; }
void Work(){
N = read();
A[1] = read();
for(reg int i = 2; i <= N; i ++){
scanf("%s", opt);
A[i] = read();
if(opt[0] == '-') A[i] = -A[i];
}
cnt = 0;
for(reg int i = 1; i <= N; i ++){
B[++ cnt] = A[i];
while(i != N && A[i] >= 0 && A[i+1] >= 0) B[cnt] += A[++ i];
}
suf_sum[cnt+1] = 0;
for(reg int i = cnt; i >= 1; i --) suf_sum[i] = suf_sum[i+1] + abd(B[i]);
F[cnt] = B[cnt];
for(reg int i = cnt-1; i >= 1; i --){
if(B[i] >= 0) F[i] = B[i] + F[i+1];
else if(B[i+1] >= 0) F[i] = std::max(B[i]+F[i+1], B[i]-B[i+1]+suf_sum[i+2]);
else F[i] = B[i] + suf_sum[i+1];
}
printf("%lld
", F[1]);
}
int main(){
int T_ = read();
while(T_ --) Work();
return 0;
}