洛谷P4552 [Poetize6] IncDec Sequence
题目:
思路:
题目要求原数组的任意区间的值加一或者减一 n n n次之后,数组的所有值都变成一样
求 n n n的最少值与能得到多少种结果
题目可以转换成把原数组的差分数组的值除了第一项都变成 0 0 0,每一次左端点加一或者减一,右端点减一或者加一
最少次数我们可以再差分数组找到一对对的正数与负数or负数与正数,因为原数组 [ l , r ] [l,r] [l,r]区间加一或者减一,差分数组就是 d i f f [ l ] + 1 ∣ ∣ − 1 diff[l]+1||-1 diff[l]+1∣∣−1并且 d i f f [ r + 1 ] − 1 ∣ ∣ + 1 diff[r+1]-1||+1 diff[r+1]−1∣∣+1
这样可以一步当两步,所以我们只要求出差分数组除了第一项的正数和与负数的绝对值和,直到正数或者负数用完,剩下的就一步一步加或者减
例:
b
i
f
f
[
]
=
1
,
1
,
0
,
−
1
,
0
biff[]=1,1,0,-1,0
biff[]=1,1,0,−1,0
这样的话我们就可以一次加减处理完
b
i
f
f
[
]
=
1
,
1
,
1
,
−
1
,
0
biff[]={1,1,1,-1,0}
biff[]=1,1,1,−1,0
如果正负不平衡的话就是正数和与负数和较大的那个,因为我们处理较大的那一个的时候,顺便可以把较小的处理
能得到多少种结果就是找 d i f f [ 1 ] diff[1] diff[1]能够有多少种不一样的值,这个值就是剩下的一步步加或者减的次数,也就是正负数次数较多的那个减去较小的那个
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
ll arr[100100]={0};//原数组
ll diff[100100]={0};//差分数组
ll n;
cin>>n;
for(int i=1;i<=n;i++) cin>>arr[i];
diff[1]=arr[1];
for(int i=2;i<=n;i++) diff[i]=arr[i]-arr[i-1];
ll sum=0,cont=1;//sum为最少操作次数,cont为最终能得到多少种结果
//因为无论如何都有一种结果,所以cont初始值为1
ll z=0,f=0;//正数和与负数和
for(int i=2;i<=n;i++){//从第二项开始遍历差分数组
if(diff[i]>0){
z+=diff[i];
}else{
f+=diff[i]*-1;
}
}
//因为我们遍历的时候每一项都加起来了,所以直接找较大的就好了,因为处理较大的时候可以顺便把较小的处理
sum=max(z,f);
//正数和与负数绝对值和的差值就是我们一次一次加减的次数,也就是最终能得到多少种额外的结果
cont+=abs(z- f);
cout<<sum<<endl<<cont<<endl;
return 0;
}