C. Particles

C. Particles

You have discovered n mysterious particles on a line with integer charges of c1,,cn. 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 4th particle will transform the line into [3,1,9,9].

If we then use the device on the 1st 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 (1t104). The description of the test cases follows.

The first line of each test case contains a single integer n (1n2105).

The second line of each test case contains n integers c1,,cn (109ci109).

It is guaranteed that the sum of n over all test cases does not exceed 2105.

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 4th particle, then on the 1st particle (as described in the statement), and finally use the device on the new 3rd particle followed by the 1st particle.

In the second test case, the best strategy is to use the device on the 4th particle to transform the line into [998244353,998244353,1996488706], then on the 2nd 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.

 

解题思路

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

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

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

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

  直接暴力算的话时间复杂度是O(n2),可以发现每次都是求一个前缀的最大值,因此可以开个变量来维护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(odd imax(ai,0),even imax(ai,0))

  不过需要注意的是,如果序列中所有的数都是负数,由于我们必须要留下一个数,因此答案应该是max1in{ai}

  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

posted @   onlyblues  阅读(77)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示