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。

代码:

扫描二维码关注公众号,回复: 8562023 查看本文章
#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;
}
发布了73 篇原创文章 · 获赞 15 · 访问量 8096

猜你喜欢

转载自blog.csdn.net/ln2037/article/details/102817388