[cf1421E]Swedish Heroes
令$p_{i}$为最终$a_{i}$之前的系数($p_{i}\in \{-1,1\}$),则有$n+\sum_{i=1}^{n}[p_{i}=-1]\equiv 1(mod\ 3)$
证明:对于两个满足这一条件的区间(初始$1+0\equiv 1(mod\ 3)$),合并后有仍然满足这一条件
但并不是满足这个条件就一定可行,例如$p_{i}=\{1,-1,1,...,1\}$(长度超过1)时满足但不可行
对于$p_{i}\ne\{1,-1,1,...,1\}$,则其一定可以被拆成两段,使得都满足$n+\sum_{i=1}^{n}[p_{i}=-1]\equiv 2(mod\ 3)$(取反后即模3余1),然后分类讨论:
1.两段中没有$\{1,-1,1,...,1\}$,通过归纳法可以证明一定可行;
2.两端中有一段(可以有2段)是$\{1,-1,1,...,1\}$,不妨假设第二段是,那么可以将分割点+2,不改变两边对于3的模数,直至划分为$[1,n-1]$和$[n,n]$,同样可以用归纳法来证明
通过这些,我们就证明了对于$p_{i}\ne\{1,-1,1,...,1\}$,都一定可行
根据这一性质,设$f[i][j]$表示前$i$个数,$-1$的个数模3余$j$,强制前$i$个位置中与$\{1,-1,1,...,1\}$不同的最大值,转移考虑不同的位置即可,答案即$f[n][(1-n)%3]$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 int n,a[N]; 5 long long sum[N],f[N][3]; 6 int main(){ 7 scanf("%d",&n); 8 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 9 if (n==1){ 10 printf("%d",a[1]); 11 return 0; 12 } 13 for(int i=1;i<=n;i++) 14 if (i&1)sum[i]=sum[i-1]+a[i]; 15 else sum[i]=sum[i-1]-a[i]; 16 f[1][1]=-a[1]; 17 f[1][0]=f[1][2]=-1e16; 18 for(int i=2;i<=n;i++){ 19 for(int j=0;j<3;j++)f[i][j]=-1e16; 20 if (i&1)f[i][(i+1)/2%3]=sum[i-1]-a[i]; 21 else f[i][(i-1)/2%3]=sum[i-1]+a[i]; 22 for(int j=0;j<3;j++)f[i][j]=max(f[i][j],max(f[i-1][j]+a[i],f[i-1][(j+2)%3]-a[i])); 23 } 24 printf("%lld",f[n][(N-3-n)%3]); 25 }