CF1038D Slime(思維+列舉+貪心)(來自洛谷)
阿新 • • 發佈:2020-07-26
洛谷地址: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; } }