IncDec Sequence(差分)

給定一個長度爲 n(n≤105)(n \leq 10^5 )(n≤105) 的數列a1,a2,…,an{a_1,a_2,…,a_n}a1​,a2​,…,an​,每次可以選擇一個區間 [l,r],使下標在這個區間內的數都加一或者都減一。
求至少需要多少次操作才能使數列中的所有數都一樣,並求出在保證最少次數的前提下,最終得到的數列可能有多少種。
輸入描述:

第一行一個正整數n。
接下來n行,每行一個整數,第i+1行的整數表示aia_iai​。

輸出描述:

第一行輸出最少操作次數。
第二行輸出最終能得到多少種結果。

輸入
4
1
1
2
2

輸出
1
2

#求原序列的差分數組,題意等價於將差分數組裏在[2, n]區間內的數都變爲零所需要的操作次數。
令正數的和爲 sumPOS, 負數的絕對值之和爲 sumPos。
接下來分類討論:

1.若差分數組裏有正數和負數,那麼我們儘量選擇絕對值相等的一對數進行操作。
2.若只有正數或負數,那麼對此項與第一項或者此項與第 n + 1項進行操作。

由此得出最少操作 min(sumPos, sumNeg) + abs(sumPos - sumNeg)次, 即max(sumPos, sumNeg)。

根據類型2,可得結果的種類數爲 abs(sumPos - sumNeg) + 1。

代碼:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

typedef long long ll;
const int maxn = 1e6 + 10;
int db[maxn];
int a[maxn];

int main()
{
	int n;
	cin >> n;
	ll sumPos = 0, sumNeg = 0;
	for(int i = 1; i <= n; i++)
		cin >> a[i];
	db[1] = a[1];
	db[n + 1] = -a[n];
	for(int i = 2; i <= n; i++)
		db[i] = a[i] - a[i - 1];
	for(int i = 2; i <= n; i++)
		if(db[i] > 0)
			sumPos += db[i];
		else if(db[i] < 0)
			sumNeg -= db[i];
	
//	cout << max(sumPos, sumNeg) << endl;
	cout << min(sumPos, sumNeg) + abs(sumPos - sumNeg) << endl;
	cout << abs(sumPos - sumNeg) + 1 << endl;
	return 0;
}
發佈了95 篇原創文章 · 獲贊 18 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章