每日一題---後綴表達式

在這裏插入圖片描述
這題其實主要涉及的是分類貪心的思想,而且這道題貪心的思路並不僅限於數字順序的問題,還可以加括號,例如:
0 2
1 2 3
3−1−2=03−1−2=0 不對,3−(1−2)=43−(1−2)=4 正確
1 2
1 2 3 4
正確的順序應該是 4+3−(1−2)=4+3+2−14+3−(1−2)=4+3+2−1
也就是說,最少可以只有一個減號起作用,其餘的減號全部負負得正。

題目的數據範圍裏面可以有負數,後綴表達式實際上是隱藏括號的,我們也可藉助這一特點來變負爲正。
1 1
-3 -2 -1
(−2)+(−1)−(−3)(−2)+(−1)−(−3) 不對,實際情況應該是 (−1)−((−2)+(−3))(−1)−((−2)+(−3))
所以,這裏我們要根據是否有負數存在以及負數和總個數的關係進行條件判斷:
如果負數個數不等於總個數
3 3
-1 -1 2 2 2 2 2
可以寫成 2+2+2−((−1)+2)−(−1)2+2+2−((−1)+2)−(−1)
最後負數全部能轉換爲正數
如果負數個數等於總個數
3 3
-2 -1 -1 -1 -1 -1 -1
應該是 (−1)−((−1)+(−1)+(−2)+(−1))−(−1)−(−1)(−1)−((−1)+(−1)+(−2)+(−1))−(−1)−(−1)
此時,因爲一共有 n+mn+m 個正負號,n+m+1n+m+1 個數字,所以,必然有一個負數不能被轉換爲正數,根據貪心的理論,這個數字的絕對值應該最小,即負數最大。代碼如下:

#include<bits/stdc++.h>
using namespace std;
int a[200020]; 
int main(){
	long long n,m,sum=0,z=0;
	cin>>n>>m;
	n=n+m+1;//正號的個數之後用不到 
	for(int i=0;i<n;i++){
		cin>>a[i];
		sum+=a[i];
		if(a[i]<0){
			z++;//統計負數的個數,方便後面進行判斷 
		}
	}
	sort(a,a+n);//排序 
	if(m){//判斷是否有負號,如果沒有負號,那麼最大值就是sum 
		if(z){//判斷是否有負數 
			if(z==n){//判斷負數個數和總個數的關係 
				for(int i=0;i<z-1;i++){//a[z-1]爲最大值,即絕對值最小值 
					sum-=2*a[i];
				}
			}else{
				for(int i=0;i<z;i++){
					sum-=2*a[i];
				}
			}
		}else{
			sum-=2*a[0];
		}
	}
	cout<<sum<<endl;
	return 0;
}

其實這題主要是負數有點點麻煩,因爲這樣需要分情況討論,根據負數個數來進行分類,比如
1 1
-3 -2 -1
如果按照我們開始的思路,這裏的順序就應該是
(-2)+(-1)-(-3)
但實際情況應該是
(-1)-((-2)+(-3))
所以這裏我們要根據是否有負數存在已經負數和總個數關心進行條件判斷
如果負數數量不等於於總個數
3 3
-1 -1 2 2 2 2 2
可以寫成
2+2+2-((-1)+2)-(-1)
最後負數全部能轉換爲正數
如果負數數量等於總個數,
3 3
-2 -1 -1 -1 -1 -1 -1
-1-((-1)+(-1)+(-2)+(-1))-(-1)-(-1)
因爲一共有m+n個正負號,但我有m+m+1個數字,所有必然有一個負數不能被轉換爲正數,根據貪心的理論,這個數字的絕對值應該最小,因爲全爲負數,等價於這個數字應該最大。
總的來說,雖然這題代碼看着貌似不難,但分類考慮以及這裏面的邏輯需要仔細斟酌纔行,就思維量上來說這題通過還是比較不容易的。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章