CodeForces - 1038D Slime 思维

推荐一边个人认为比较好的博客:https://blog.csdn.net/qq_37594941/article/details/82589288

题意:给出一个长度为n的数列,每个数都可以和左边的数或者右边的数结合(紧挨着的),结合后的结果为结合的数减去被结合的数得到的值,结合n-1次后,只剩下一个数,问这个数最大是多少。

Solution:只要弄明白了下面这个事实,这个题就好做了:至少有一个数没有做过被减数,并且有且只有一个数没有做过减数,也就是说,至少有一个数没有减过其他的数,并且至少有一个数没有被其他数减过,最关键的是要理解:除了这两个数以外,其他任何数都可以选择被加或者被减,如果理解这个了,这个题就非常好做了。(只需要用数列中最大的数减去最小的数,然后对与剩下的n-2个数,正的就加,负的就减,显然,得到的结果就是最大的)

那么,怎样证明这个事实呢?

首先,n个数要变成1个数,一定会有一个数没有减过其他数,并且有且只有一个数被其他数减过。

除了这两个数以外,其他任何数都可以选择被加或者被减 ,证明如下:

假设这n个数为:

a1  a2  a3  a4  a5  x  y  z  a6  a7  

对于z来说,如果你想减他,只需要让y和z去结合,得到y-z,这个数列就变成了:a1  a2  a3  a4  a5  x  y-z  a6  a7 ,这就实现了减去z;

如果你想加他,只需要先让y和z先结合,得到(y-z),然后  让x和(y-z)结合,得到x-(y-z),即:x-y+z,这个数列就变成了:a1  a2  a3  a4  a5  x-y+z  a6  a7 ,这就实现了加上z。

对于其他数也是同样的道理。

还有就是最终结果会爆int,所以要用long long。

AC_Code:

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 1000010
const double pi=acos(-1.0);
using namespace std;
int a[500010];
int main()
{
    int n;
    cin>>n;
    for(int i=0; i<500010; i++)
        a[i]=0;
    for(int i=0; i<n; i++)
        scanf("%d",&a[i]);
    if(n==1)    //显然,如果n等1,那么结果就是a[0]
    {
        cout<<a[0];
        return 0;
    }
    if(n==2)
    {
        cout<<fabs(a[1]-a[0]);  //如果n等2,那么结果就是他们两个差的绝对值,即让大的那个是去结合小的那个数
        return 0;
    }
    sort(a,a+n);
    //int会爆
    ll ans=a[n-1]-a[0]; //因为至少有一个数没有结合过,且有且只有一个数没有被结合过,就让最小的那个数做没有结合过的,让最大的那个数做没有被结合过的
    for(int i=1; i<n-1; i++)
    {
        if(a[i]>=0)     //正的就加
            ans+=a[i];
        else            //负的就减
            ans-=a[i];
    }
    cout<<ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/flyzer/article/details/83659793
今日推荐