Codeforces Round #508 (Div. 2) D. Slime

D. Slime

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

题意:给你n个数,任意相邻两数作差x=a[i]-a[j],只要i!=j即可作差,所得x将代替原来的a[i],a[j],最终会剩下一个数,问你这个数最大是多少?

思路:一开始以为是dp,推了几组数据发现有规律的。

我们可以分为三类:全是正数,全是负数,正负都有。

对于1,2,3,4,我们推一下会发现,无论怎么排列这几个数,最终都能求得最大值8.

1.所以如果整个数组都是正号的,直接排序,让x=a[1]-a[2]构造一个负数,接下来x=x-a[j](j>=3&&j<n)积累这个差,会积累到一个特别小的负数,用a[n]-x即为最大值。整个数组负号的可以全变正号,直接用上面的方法。

2.对于异号的数组,依然排序,找到最大的负数,即从右向左查,出现的第一个负数x,位置pos。由于x的右边全是正数,那么继x=x-a[j],去积累差,最后x=a[n]-x,得到目前最大。接下来用x直接减去pos以左的全部负数,即得最大值。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a[500050],n;
int main()
{
    while(~scanf("%lld",&n))
    {
        for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);
        if(n==1){printf("%lld\n",a[1]);continue;}
        sort(a+1,a+n+1);
        ll f1,f2,sum;
        f1=f2=0;
        for(ll i=1;i<=n;i++)
        {
            if(a[i]>=0)f1=1;   //代表有正数和0
            if(a[i]<0)f2=1;   //代表有负数
        }
        if(f1&&f2==0)   //只有正数时
        {
            sum=a[1];
            for(ll i=2;i<=n;i++)
            {
                sum=sum-a[i];   //积累差
            }
            sum=-sum;
        }
        else if(f1==0&&f2)   //只有负数时
        {
            for(ll i=1;i<=n;i++)a[i]=-a[i];
            sort(a+1,a+n+1);
            sum=a[1];
            for(ll i=2;i<=n;i++)
            {
                sum=sum-a[i];
            }
            sum=-sum;
        }
        else
        {
            ll pos;
            for(ll i=n;i>=1;i--)   //找到右边第一个负数pos
            {
                if(a[i]<=0)
                {
                    pos=i;
                    break;
                }
            }
            sum=a[pos];
            for(ll i=pos+1;i<=n;i++)
            {
                sum=sum-a[i];   //积累差
            }
            sum=-sum;
            for(ll i=1;i<pos;i++)sum-=a[i];   //向左积累回去
        }
        printf("%lld\n",sum);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值