【题解】AT2273 Addition and Subtraction Hard(DP)
一个数对答案最终的贡献是(+/-1),决定一个数的在最终答案里的贡献在于它在多少个(-(dots))之中。
考虑一个(O(n^3)DP),设(dp(i,j))表示确定(i)个数字前面的左括号,总共有(j)个"-("括号需要到时候括回来,根据(j)的奇偶性就能够转移。
但是实际上我们不需要记录括号具体的数量,我们只需要知道奇偶性即可。此外,由于一个位置可以括多个括号回来( 像这样()ig)Big)) ),所以(>1)的括号既可以看做偶数个,也可以看做奇数个。所以设(dp(i,0/1/2))表示这个位置有(0/1/>1)个括号需要括回来,可以选择现在括,也可以留到以后。
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
inline int qr(){
int ret=0,f=0,c=getchar();
while(!isdigit(c)) f|=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=1e5+5;
int data[maxn],n;
ll dp[maxn][3];
int main(){
memset(dp,0xcc,sizeof dp);
n=qr();
for(int t=1;t<=n;++t) data[t]=qr();
dp[0][0]=0;
for(int t=1;t<=n;++t)
if(data[t]>0){
dp[t][0]=max({dp[t][0],dp[t-1][0]+data[t],dp[t-1][1]+data[t],dp[t-1][2]+data[t]});
dp[t][1]=max({dp[t][1],dp[t-1][1]-data[t],dp[t-1][2]-data[t]});
dp[t][2]=max({dp[t][2],dp[t-1][2]+data[t]});
}else{
data[t]=-data[t];
dp[t][0]=max({dp[t][0],dp[t-1][0]-data[t],dp[t-1][1]-data[t],dp[t-1][2]-data[t]});
dp[t][1]=max({dp[t][1],dp[t-1][0]-data[t],dp[t-1][1]+data[t],dp[t-1][2]+data[t]});
dp[t][2]=max({dp[t][2],dp[t-1][1]+data[t],dp[t-1][2]+data[t]});
}
cout<<max({dp[n][0],dp[n][1],dp[n][2]})<<endl;
return 0;
}