這道題目是很容易進坑的。c++
坑就在於,第一眼看上去,只有加號和減號,哦~簡單,把最小的都減掉就完事了。spa
然鵝這道題目的背景是後綴表達式,在將中綴表達式轉化成後綴表達式的過程當中是要把括號什麼的都去掉的,也就是說咱們在運算的過程當中,有可能經過巧妙利用括號,來尋找到更優的答案。code
0 2blog
3 2 1string
按照錯誤想法的答案是3-2-1=0it
然鵝,他能夠這樣3-(1-2)=4io
(由於我也不知道本身能不能掰扯清楚class
設ans爲最終求的答案,sum爲全部數的絕對值之和,maxx爲全部數中的最大值,minn爲全部數中的最小值。方法
分狀況討論:im
①若是全部的數都>0,ans=sum-2*minn。
②若是全部的數都<0,則ans=sum+2*maxx。
③上述兩種狀況都不符合,即正負均有,則ans=sum。
對上面三種狀況作出解釋:
則只須要A1+A2+...+Am-(minn-Am+1-...-An) = A1+A2+...+An-minn。
你會發現,只要全部數都爲正數,那麼只須要像上式那樣構造,就能獲得一個只須要損失一個最小值的答案,即ans=sum-2*minn。
則只須要maxx-A1-A2-...-Am-(A(m+1)+A(m+2)+...+An) = -A1-A2-...-An+maxx。
你會發現,只要全部數都爲負數,那麼只須要像上式那樣構造,就能獲得一個只須要損失一個絕對值最小的答案,即ans=sum+2*maxx。由於所有都是負數,加上絕對值最小的負數損失最小,所以加上的是maxx,即最大值。
則你會發現,不管你怎麼樣構造,你都能構造出來一種方法,使得最終答案爲全部數的絕對值之和,即正數儘可能都用加號,碰到沒有加號的時候就用負號配合上括號便可保留正數;負數儘可能都用負號,碰到沒有負號的時候就用加號配合上括號便可把負數轉化爲相反數。
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; typedef long long ll; const ll maxn=1e6+50; ll a[maxn]; int main() { ll n,m; scanf("%lld %lld",&n,&m); ll maxx=-4e18,minn=4e18,sum=0; for(ll i=1;i<=n+m+1;i++) { scanf("%lld",&a[i]); if(a[i]>0)sum+=a[i]; else sum+=(-a[i]); maxx=max(maxx,a[i]); minn=min(minn,a[i]); } ll ans; if(maxx<0)ans=sum+maxx*2; else if(minn>0)ans=sum-minn*2; else ans=sum; printf("%lld\n",ans); }