給定一個長度爲 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;
}