CF1038D Slime(思维+枚举+贪心)(来自洛谷)

洛谷地址:https://www.luogu.com.cn/problem/CF1038D

题意:

n只史莱姆,每一个史莱姆可以吃相邻的左或右,它的分数就变成:它的分数-被吃的分数

求最大的剩余值。

解析:

如果对过程进行太多的分析的话,问题就会变得很复杂。刚开始想的是,把所有能算出来的负数弄出来,但是情况又有好多,接着又想到dp....越想越多。

这个时候,尝试分情况讨论,简化具体过程,这是一个教训!

1:正负均有,要想结果最大,肯定是让负数尽可能多,然后让正数去减它。

假设有x个正数,让负数把x-1的正数全变成负数,让最后的那个正数去减所有负数,得到的结果就是所有数的绝对值之和。

既然正负均有,那么肯定存在正负相邻,所以这个结论是正确的。

2:全为正

参照一,如果弄出一个负数来,那么结果也跟绝对值有关,就是:去掉它俩的剩余数的绝对值之和+它俩吃出的价值(取正,因为吃左吃右都可以)

这个时候就可以O(N)枚举相邻数了。

全为负同理。

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<string.h>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
ll a[maxn];
ll b[maxn];
int vis[maxn];
int main()
{
    int n;
    cin>>n;
    int tot=0;
    int z=0,f=0;
    ll sum=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=abs(a[i]);
        if(a[i]>0)
            z++;
        if(a[i]<0)
            f++;
    }
    if(n==1)
        cout<<a[1]<<endl;
    else if(z>0&&f>0)
    {
        cout<<sum<<endl;
    }
    else
    {
        ll ans=0;
        for(int i=2;i<=n;i++)
        {
            ans=max(ans,sum-abs(a[i])-abs(a[i-1])+abs(a[i]-a[i-1]));
        }
        cout<<ans<<endl;
    }
}

 

posted @ 2020-07-26 18:08  liyexin  阅读(147)  评论(0编辑  收藏  举报