C. Particles

发布时间 2023-07-12 20:13:51作者: onlyblues

C. Particles

You have discovered $n$ mysterious particles on a line with integer charges of $c_1,\dots,c_n$. You have a device that allows you to perform the following operation:

  • Choose a particle and remove it from the line. The remaining particles will shift to fill in the gap that is created. If there were particles with charges $x$ and $y$ directly to the left and right of the removed particle, they combine into a single particle of charge $x+y$.

For example, if the line of particles had charges of $[-3,1,4,-1,5,-9]$, performing the operation on the $4$th particle will transform the line into $[-3,1,9,-9]$.

If we then use the device on the $1$st particle in this new line, the line will turn into $[1,9,-9]$.

You will perform operations until there is only one particle left. What is the maximum charge of this remaining particle that you can obtain?

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 10^4$). The description of the test cases follows.

The first line of each test case contains a single integer $n$ ($1 \le n \le 2 \cdot 10^5$).

The second line of each test case contains $n$ integers $c_1,\dots,c_n$ ($-10^9 \le c_i \le 10^9$).

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

Output

For each test case, output one integer, the maximum charge of the remaining particle.

Example

input

3
6
-3 1 4 -1 5 -9
5
998244353 998244353 998244353 998244353 998244353
1
-2718

output

9
2994733059
-2718

Note

In the first test case, the best strategy is to use the device on the $4$th particle, then on the $1$st particle (as described in the statement), and finally use the device on the new $3$rd particle followed by the $1$st particle.

In the second test case, the best strategy is to use the device on the $4$th particle to transform the line into $[998244353,998244353,1996488706]$, then on the $2$nd particle to transform the line into $[2994733059]$. Be wary of integer overflow.

In the third test case, there is only one particle, so no operations can be performed.

 

解题思路

  好久没写博客啦,前段时间事情有点多,主要还是比较懒

  昨晚写的时候一直按照题目所给的过程步骤来做,即选择一个数从中删去然后左右两边的数相加变成一个新数。然后写了假的贪心做法没过,卡在那里很久。然后莫名其妙想到既然你要删掉某些数,然后剩下的数合并成一个,那我直接看最后可以保留哪些数来合并一个不就好了,然后就做出来了。

  其实通过模拟几组数据就可以发现最终能够保留下来的数所在位置的下标奇偶性必然是相同的。考虑保留位置$i$和$j$这两个位置上的数($[i+1, j-1]$内的数都删去),如果$i$和$j$的奇偶性相同,那么$[i+1, j-1]$范围内就包含$j-i-1$个数,即删掉了奇数个数。我们可以构造出一种删除的方案,即每次删掉中间的那个数,然后相邻两边的数合并变成中间的数,下次继续删除中间的数,这样就可以把$[i+1, j-1]$内的数都删除,当删除最后的那个数时,$i$和$j$位置上的数就会合并成一个。相反如果$i$和$j$的奇偶性不同,那么$[i+1, j-1]$内就包含偶数个数,可以发现无论我们怎么删除,都无法将这偶数个数删除。

  因此问题就变成了分别在奇数位置和偶数位置中选择哪些数相加可以得到的结果最大。这里可以用dp来实现。定义状态$f(i)$表示从前$i$个数且与$i$奇偶性相同的数中的选,且最后选择$a_i$的所有方案中,和的最大值。因此状态转移方程就是$$f(i) = \max\limits_{\begin{array}{center} 1 \leq j \leq i \\ j \equiv i \pmod{2} \end{array}} \{ f(j) \} + a_i$$

  直接暴力算的话时间复杂度是$O(n^2)$,可以发现每次都是求一个前缀的最大值,因此可以开个变量来维护$f(i)$的前缀的最大值,时间复杂度就降到了$O(n)$。

  AC代码如下:

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

  还有贪心的做法,在奇偶性相同的位置我们直接把选所有的正数选出来就好了,因此答案就是$$\max\left(\sum_{\text{odd }i} \max(a_i,0),\sum_{\text{even }i} \max(a_i,0)\right)$$

  不过需要注意的是,如果序列中所有的数都是负数,由于我们必须要留下一个数,因此答案应该是$\max\limits_{1 \leq i \leq n} \{ a_i \}$。

  AC代码如下,时间复杂度为$O(n)$:

 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     LL s[2] = {0};
10     int maxv = -2e9;
11     for (int i = 0; i < n; i++) {
12         int x;
13         scanf("%d", &x);
14         s[i & 1] += max(0, x);
15         maxv = max(maxv, x);
16     }
17     if (maxv < 0) printf("%d\n", maxv);
18     else printf("%lld\n", max(s[0], s[1]));
19 }
20 
21 int main() {
22     int t;
23     scanf("%d", &t);
24     while (t--) {
25         solve();
26     }
27     
28     return 0;
29 }

 

参考资料

  Codeforces Round #884 (Div. 1 + Div. 2) Editorial:https://codeforces.com/blog/entry/118128