acm-(思维、找规律、打表)Codeforces Round #676 (Div. 2) E. Swedish Heroes

24 篇文章 0 订阅
12 篇文章 0 订阅

题面
传送门
首先答案一定是 ∑ i = 1 n b i a i , ( b i = − 1 , 1 ) \sum_{i=1}^nb_ia_i,(b_i=-1,1) i=1nbiai,(bi=1,1)
我们考虑最终的答案中的 { b i } \{b_i\} {bi}序列有何性质,假设其中 − 1 -1 1 x x x个, 1 1 1 y y y个,那么满足 ( 2 x + y ) % 3 = 1 (2x+y)\%3=1 (2x+y)%3=1

这个可以通过打表看出(我其实看不出 ),这里给出一个证明:
利用数学归纳法来证明,每次我们都会合并两个序列,考虑两个序列的性质,若两个序列都满足 ( 2 x + y ) % 3 = 1 (2x+y)\%3=1 (2x+y)%3=1,假设第一个序列 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),第二个序列 ( x 2 , y 2 ) (x_2,y_2) (x2,y2),则有合并后的序列为 ( y 1 + y 2 , x 1 + x 2 ) (y_1+y_2,x_1+x_2) (y1+y2,x1+x2),则 [ ( 2 y 1 + 2 y 2 + x 1 + x 2 ) % 3 + ( 2 x 1 + y 1 ) % 3 + ( 2 x 2 + y 2 ) % 3 = [ 3 ( x 1 + x 2 + y 1 + y 2 ) ] % 3 ] % 3 = 0 ⇒ [ ( 2 y 1 + 2 y 2 + x 1 + x 2 ) % 3 + 1 + 1 ] % 3 = 0 ⇒ ( 2 y 1 + 2 y 2 + x 1 + x 2 ) % 3 = 1 [(2y_1+2y_2+x_1+x_2)\%3+(2x_1+y_1)\%3+(2x_2+y_2)\%3=[3(x_1+x_2+y_1+y_2)]\%3]\%3=0\Rightarrow [(2y_1+2y_2+x_1+x_2)\%3+1+1]\%3=0\Rightarrow (2y_1+2y_2+x_1+x_2)\%3=1 [(2y1+2y2+x1+x2)%3+(2x1+y1)%3+(2x2+y2)%3=[3(x1+x2+y1+y2)]%3]%3=0[(2y1+2y2+x1+x2)%3+1+1]%3=0(2y1+2y2+x1+x2)%3=1。即合并后的序列仍然满足该性质。最开始的时候每个序列都为 ( 0 , 1 ) (0,1) (0,1),显然满足 ( 2 x + y ) % 3 = 1 (2x+y)\%3=1 (2x+y)%3=1,因此最终合并出来的答案也满足 ( 2 x + y ) % 3 = 1 (2x+y)\%3=1 (2x+y)%3=1

也就是说我们只要枚举可能的满足上述条件的 { b i } \{b_i\} {bi}序列,然后计算答案取最大值即可。

不过可惜上述条件只是必要条件,考虑一个反例 1 , − 1 , 1 , − 1 , . . 1,-1,1,-1,.. 1,1,1,1,..,也就是正负一交替的情况,这种情况不能出现,因为我们合并的最开始的两个数最后的符号一定相同,并且这两个数相邻,这与反例的情况不符。

因此我们需要枚举的 { b i } \{b_i\} {bi}序列需要满足:1. ( 2 x + y ) % 3 = 1 (2x+y)\%3=1 (2x+y)%3=1。2.存在相邻项符号相同。

直接枚举 { b i } \{b_i\} {bi}不太行,于是考虑 d p dp dp,设 d p [ i ] [ j ] [ k ] [ h ] dp[i][j][k][h] dp[i][j][k][h]表示考虑到前 i i i位,满足 ( 2 x + y ) % 3 = j (2x+y)\%3=j (2x+y)%3=j b i = { − 1 i f    k = 0 1 i f    k = 1 b_i=\begin{cases}-1&if\;k=0\\1&if\;k=1\end{cases} bi={11ifk=0ifk=1 [ h = 1 ] = [ 是 否 存 在 相 邻 项 符 号 相 同 ] [h=1]=[是否存在相邻项符号相同] [h=1]=[]情况的序列最大值。

转移方程也很好写,具体参照代码即可。

ll a[maxn],dp[maxn][3][2][2];
 
int main(){
	int n=rd();
	FOR(i,1,n+1)a[i]=rd();
	if(n==1)return wrn(a[1]),0;
	memset(dp,-0x3f,sizeof(dp));
	dp[1][2][0][0]=-a[1];
	dp[1][1][1][0]=a[1];
	FOR(i,1,n){
		FOR(j,0,3){
			FOR(l,0,2)
			FOR(k,0,2){
				dp[i+1][(j+2)%3][0][k|(l==0)]=max(dp[i+1][(j+2)%3][0][k|(l==0)],dp[i][j][l][k]-a[i+1]);
				dp[i+1][(j+1)%3][1][k|(l==1)]=max(dp[i+1][(j+1)%3][1][k|(l==1)],dp[i][j][l][k]+a[i+1]);
			}
		}
	}
	printf("%lld\n",max(dp[n][1][1][1],dp[n][1][0][1]));
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值