CODEFORCE___301A-----分析题(纪念第一次水掉的CF)

题目地址:http://codeforces.com/problemset/problem/301/A

题目的意思,给2*n-1个数,每次在这些数里面取n个数乘以-1,然后问你经过任意次这样的操作后

给出这些数的总和的最大值

也就是说要使得这些数尽量的都为正数,这样和才最大

感谢ACdream群的朋友们,没有你们的点拨,我估计还是想不出来

已知每次要取n个,假设这2*n-1个数里面有k个负数,下面我们可以来讨论一下

1)首先如果k=n的话,就特别好说了,直接*-1就完事,也就是所有数的绝对值之和

2)如果n为奇数

k<n

那么我们可以每次从k个里面取x个负数,从剩下的正数里面取n-x个正数

因为k<n,所以我们可以让负数慢慢增加到n,然后再一次性*-1,解决问题

我们来看n-x和x

减少了x个负数,增加了n-x个负数,也就是总的增加了n-2*x个负数

因为n是奇数,而2*x是偶数,且n不为0

奇数-偶数=奇数,所以在n为奇数的条件下,我们可以增加或减少奇数个负数

这样我们就可以使负数的个数变为n个,然后再*-1解决问题

k>n

在前面提到了,可以减少奇数个,所以我们也可以通过刚刚那种方式解决,这个不用赘述。

那可能为想,增加或减少奇数个k就一定可以为n吗

答案是肯定的,因为1是奇数

3)如果n是偶数

同样还是取x个负数,n-x个正数

一共增加了n-2*x个负数

因为n为偶数,所以每次只能增加或减少偶数个负数

那么这里就要注意了,如果k是奇数的话,每次增加或减少偶数个

怎么也无法变成n

但是如果k是偶数的话,则可以成为n

那如果k是奇数的时候怎么求出最大值呢?

我们将k减少到1,也就说最多只会出现一个负数

因为正负都是可以调换的

所以我们可以先求出所有数的绝对值之和,然后减去最小的那个的二倍

就是我们要求的答案

下面上代码:

#include<cstdio>
using namespace std;
const int maxn = 200+10;

int a[maxn];
int sum;

int main()
{
    int n;
    int fu;
    int min;
    while(~scanf("%d",&n))
    {
        fu=0;
        min=0x3f3f3f3f;
        sum=0;
        for(int i=1;i<=2*n-1;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]<0)
            {
                a[i]=-a[i];
                fu++;
            }

            if(a[i]<min)
                min=a[i];
            sum+=a[i];
        }
        if((n&1) || !(fu&1))
            printf("%d\n",sum);
        else
            printf("%d\n",sum-2*min);
    }
    return 0;
}


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值