D. Slime
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
There are nn slimes in a row. Each slime has an integer value (possibly negative or zero) associated with it.
Any slime can eat its adjacent slime (the closest slime to its left or to its right, assuming that this slime exists).
When a slime with a value xx eats a slime with a value yy, the eaten slime disappears, and the value of the remaining slime changes to x−yx−y.
The slimes will eat each other until there is only one slime left.
Find the maximum possible value of the last slime.
Input
The first line of the input contains an integer nn (1≤n≤5000001≤n≤500000) denoting the number of slimes.
The next line contains nn integers aiai (−109≤ai≤109−109≤ai≤109), where aiai is the value of ii-th slime.
Output
Print an only integer — the maximum possible value of the last slime.
Examples
input
Copy
4 2 1 2 1
output
Copy
4
input
Copy
5 0 -1 -1 -1 -1
output
Copy
4
Note
In the first example, a possible way of getting the last slime with value 44 is:
In the second example, the first slime can keep eating slimes to its right to end up with a value of 44.
假设有四个数a,b,c,d。手动去各种模拟,可以发现:
比如b吃c,再吃d,a再吃b,最后的答案是a-b+c+d
比如a吃b,吃c,然后d吃a,最后是d+c+b-a.
如果发现了这一点,就容易发现其实最后的和是各个数字前面加+/-的,而且+和-至少同时都有一个。
那么看一段有正负的数字,想让最后和最大,就让其中正的+号,负的-号,然后累加。
如果是全正,就让其中最小的成负号。如果全负就让最大的正号。
代码的时候先sum统计一遍绝对值和,然后看序列的情况。注意统计的时候sum是全部正数加的,比如全正该加负号的数也加了正进去,所以减去的时候减两倍。负数同理。
#include
#include
#include
#include
#include
#include
然后看了看cf的官方题解,说是还可以dp,原来我是没想出这个dp怎么写的。
“It could have also been solved with DP where we check if - sign has been taken or not, and + sign has been taken or not. (4nstates)”
就是说dp的定义是定义+和-有无添加过了。
dp[i][1/0][1/0]:共有i个数且到第i个数+/-号有无添加过的最大值
考虑状态转移:
1.如果当前到i这个数且前i个数只添加过+: dp[i][1][0]=dp[i-1][1][0]+a[i];
2.如果当前到i这个数且前i个数只添加过-: dp[i][0][1]=dp[i-1][0][1]-a[i];
3.如果到当前i这个数且前i个数加过+和-:
dp[i][1][1]=max(dp[i][1][1],dp[i-1][1][0]-a[i]);
dp[i][1][1]=max(dp[i][1][1],dp[i-1][0][1]+a[i]);
dp[i][1][1]=max(dp[i-1][1][1],dp[i-1][1][1]+abs(a[i]);//如果添加过了那么最大值看当前这个数是正是负,正直接+,负填负号。
总结:相邻数字的操作可以拿具体例子,也可以设字母相邻去多操作操作。有时候具体容易发现,有时候字母更容易发现,这题就是字母更容易发现。构造出来发现至少有一个+和-,且发现了最后答案就是在原有的式子数字上前面添加+/-的时候,就好思考了。
这题的dp如果没有先思考出构造的方式,是十分难以dp的。思考出来了其实也没必要dp。但是为了锻炼一下dp,还是尝试了dp。
是道不错的题
博客撰写过程中参考了:
https://www.cnblogs.com/dilthey/p/10492657.html
https://blog.csdn.net/jziwjxjd/article/details/106858999