IncDec序列:差分+贪心

IncDec序列

题目描述:

给定一个长度为 n 的数列 a1,a2,…,an,每次可以选择一个区间[l,r],使下标在这个区间内的数都加一或者都减一。

求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。

输入格式:

第一行输入正整数n。

接下来n行,每行输入一个整数,第i+1行的整数代表ai。

输出格式:

第一行输出最少操作次数。

第二行输出最终能得到多少种结果。

数据范围:

0<n≤10^5,

0≤ai<21474836480ai<2147483648

输入样例:

4
1
1
2
2

输出样例:

1
2

解题思路:

随意在[l,r]  +1或者-1,具体分一下几种情况:

1. l,r都在中间  2<=l,r<=n。

2.前缀,l==2,2<=r<=n。

3.后缀,r==n,2<=l<=r。

4.全部,l==2,r==n,(无意义)。

修改方案可以是先局部修改,采用1,然后前后修改,采用2,3

操作次数:min(z,f)+abs(z - f)==max(z,f)    

方案数:min(z-f)+1

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
using namespace std;
#define ll long long
const int N = 100010;
int a[N];

int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) 
		scanf("%d", &a[i]);
	
	for (int i = n; i > 0; i--)			
		a[i] -= a[i - 1];				//倒序求差分数组

	ll z = 0, f = 0;
	for (int i = 2; i <= n; i++) {		//求差分数组中正负值
		if (a[i] > 0)z += a[i];
		else f -= a[i];
	}

	printf("%lld
%lld
", max(z,f), abs(z - f) + 1);

	return 0;
}


 
原文地址:https://www.cnblogs.com/52dxer/p/10530979.html