E. Negatives and Positives

E. Negatives and Positives

Given an array $a$ consisting of $n$ elements, find the maximum possible sum the array can have after performing the following operation any number of times:

  • Choose $2$ adjacent elements and flip both of their signs. In other words choose an index $i$ such that $1 \leq i \leq n - 1$ and assign $a_i = -a_i$ and $a_{i+1} = -a_{i+1}$.

Input

The input consists of multiple test cases. The first line contains an integer $t$ ($1 \leq t \leq 1000$) — the number of test cases. The descriptions of the test cases follow.

The first line of each test case contains an integer $n$ ($2 \leq n \leq 2\cdot10^5$) — the length of the array.

The following line contains $n$ space-separated integers $a_1,a_2,\dots,a_n$ ($-10^9 \leq a_i \leq 10^9$).

It is guaranteed that the sum of $n$ over all test cases does not exceed $2\cdot10^5$.

Output

For each test case, output the maximum possible sum the array can have after performing the described operation any number of times.

Example

input

5
3
-1 -1 -1
5
1 5 -5 0 2
3
1 2 3
6
-1 10 9 8 7 6
2
-1 -1

output

1
13
6
39
2

Note

For the first test case, by performing the operation on the first two elements, we can change the array from $[-1, -1, -1]$ to $[1, 1, -1]$, and it can be proven this array obtains the maximum possible sum which is $1 + 1 + (-1) = 1$.

For the second test case, by performing the operation on $-5$ and $0$, we change the array from $[1, 5, -5, 0, 2]$ to $[1, 5, -(-5), -0, 2] = [1, 5, 5, 0, 2]$, which has the maximum sum since all elements are non-negative. So, the answer is $1 + 5 + 5 + 0 + 2 = 13$.

For the third test case, the array already contains only positive numbers, so performing operations is unnecessary. The answer is just the sum of the whole array, which is $1 + 2 + 3 = 6$.

 

解题思路

  比赛的时候一直想着贪心怎么写,然后一直在那wa,最后还是老老实实写dp过了,回来看题解的时候发现还真是贪心解法,就是一直没发现题目的某个性质。

  注意到不管我们执行了多少次的操作,数组中负数个数的奇偶性总是保持不变(在一次取反后,要么是增加或者减少两个负数,要么是增加一个负数和减少一个负数)。

  因此如果一开始数组中有偶数个负数,那么我们总是可以通过若干次的操作使得负数的个数变成$0$,因此答案就是所有数的绝对值之和。

  如果一开始数组中有奇数个负数,那么最终至少要有一个负数,所有我们可以让数组中绝对值最小的那个数为负数(如果有$0$的话则选择$0$),那么答案就是其他数的绝对值之和再减去这个最小数的绝对值。

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 void solve() {
 7     int n;
 8     scanf("%d", &n);
 9     int cnt = 0, minv = 2e9;
10     LL s = 0;
11     while (n--) {
12         int x;
13         scanf("%d", &x);
14         if (x < 0) cnt++, x *= -1;    // 统计负数
15         s += x;
16         minv = min(minv, x);    // 找到绝对值最小的那个数
17     }
18     if (cnt & 1) s -= 2 * minv;    // 有奇数个负数
19     printf("%lld\n", s);
20 }
21 
22 int main() {
23     int t;
24     scanf("%d", &t);
25     while (t--) {
26         solve();
27     }
28     
29     return 0;
30 }

  再给出dp的做法。

  定义状态$f(i,0)$表示前$i$个数中,且第$i$个数没有改变正负性的所有方案的最大值。$f(i,1)$表示前$i$个数中,且第$i$个数有改变正负性的所有方案的最大值。根据前一个数$a_{i-1}$是否有改变正负性来划分集合,状态转移方程为

\begin{cases}
f(i,0) = \max\{ f(i-1,0), f(i-1,1) \} + a_i \\
f(i,1) = \max \{ f(i-1,0) -2a_{i-1}, f(i-1,1) + 2a_{i-1} \} - a_i
\end{cases}

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10;
 7 
 8 int a[N];
 9 LL f[N][2];
10 
11 void solve() {
12     int n;
13     scanf("%d", &n);
14     for (int i = 1; i <= n; i++) {
15         scanf("%d", a + i);
16     }
17     f[2][0] = a[1] + a[2], f[2][1] = -a[1] + -a[2];
18     for (int i = 3; i <= n; i++) {
19         f[i][0] = max(f[i - 1][0], f[i - 1][1]) + a[i];
20         f[i][1] = max(f[i - 1][0] - 2 * a[i - 1], f[i - 1][1] + 2 * a[i - 1]) - a[i];
21     }
22     printf("%lld\n", max(f[n][0], f[n][1]));
23 }
24 
25 int main() {
26     int t;
27     scanf("%d", &t);
28     while (t--) {
29         solve();
30     }
31     
32     return 0;
33 }

 

参考资料

  Codeforces Round #849 (Div. 4) Editorial:https://codeforces.com/blog/entry/112282

posted @ 2023-02-04 15:56  onlyblues  阅读(63)  评论(0编辑  收藏  举报
Web Analytics