洛谷地址: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; } }