cf 1421E. Swedish Heroes (dp)
题目链接:传送门
题目思路:通过观察 题解 规律 ,总结出:
1. 最后的答案 ans = Σpi * ai , pi = { -1 ,1 } ;
2. 系数集合p满足:
但是有一个特例 p = {1,-1,1,-1,... , 1} ,显然第一次选择两个个数相加,知道最后这两个数字的pi应该是相等的 ;当然 p = {-1 , 1 , -1 , ... , 1 , -1 } 也是不合规则的,但是它不美,满足上述的第二个条件
声明 dp(i,j,k) : 表示 前i个数字 ,-1的个数为j ,是否为特例 的"求和"后最大值 , k=1 表示为特例 ;
i为奇数: dp(i,j,1) <- dp(i-1,j,1) + a[i] , dp(i,j,0) <- dp(i-1,(j+2)%3,1) - a[i]; (0表示不为特例 ,求和得来的最大值,显然必须某位加-1 使得其变成 1 -1 1 -1 -1)
i为偶数: dp(i,j,1) <- dp(i-1,(j+2)%3,1) + a[i] , dp(i,j,0) <- dp(i-1,j,1) + a[i]; (使其变成 1 -1 1 1 )
dp(i,j,0) <- max{ dp(i,j,0) , dp(i-1,j,0) + a[i] , dp(i-1,(j+2)%3,0) - a[i] } ;
代码:
#include<bits/stdc++.h> /* #include<cstdio> #include<cmath> #include<cstring> #include<vector> #include<cctype> #include<queue> #include<algorithm> #include<map> #include<set> */ #pragma GCC optimize(2) using namespace std; typedef long long LL; typedef unsigned long long uLL; typedef pair<int,int> pii; typedef pair<LL,LL> pLL; typedef pair<double,double> pdd; const int N=2e5+5; const int M=8e5+5; const LL inf=1e17; const LL mod=1e8+7; const double eps=1e-5; const long double pi=acos(-1.0L); #define ls (i<<1) #define rs (i<<1|1) #define fi first #define se second #define pb push_back #define eb emplace_back #define mk make_pair #define mem(a,b) memset(a,b,sizeof(a)) LL read() { LL x=0,t=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') t=-1; while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } return x*t; } // n + cnt:op=-1 = 1 (mod 3) LL dp[N][3][2]; LL a[N]; int main() { int n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) for(int j=0;j<3;j++) for(int k=0;k<2;k++) dp[i][j][k]=-inf; if(n==1) return 0*printf("%lld\n",a[1]); dp[1][1][0]=-a[1];//写法2: j表示 -1的个数 取模3 , k 表示 该串是否为 1 -1 1 -1 1 ... dp[1][0][1]=a[1]; for(int i=2;i<=n;i++) { for(int j=0;j<3;j++) { if(i&1) { dp[i][j][1]=dp[i-1][j][1]+a[i]; dp[i][j][0]=dp[i-1][(j+2)%3][1]-a[i]; } else { dp[i][j][1]=dp[i-1][(j+2)%3][1]-a[i]; dp[i][j][0]=dp[i-1][j][1]+a[i]; } dp[i][j][0]=max(dp[i][j][0],dp[i-1][j][0]+a[i]); dp[i][j][0]=max(dp[i][j][0],dp[i-1][(j+2)%3][0]-a[i]); } } printf("%lld\n",dp[n][((1-n)%3+3)%3][0]); return 0; }