题解 P4552 【[Poetize6] IncDec Sequence】
这是一道水题
题目:
给定一个长度为 n 的数列 a1,a2,…,an,每次可以选择一个区间 [l,r],使下标在这个区间内的数都加一或者都减一。求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。
输入格式
第一行输入正整数n。
接下来n行,每行输入一个整数,第i+1行的整数代表ai。
输出格式
第一行输出最少操作次数。
第二行输出最终能得到多少种结果。
数据范围
0<n≤1e5,
0≤ai<2147483648
输入样例:
4
1
1
2
2
输出样例:
1
2
这道题,我觉得代码难度不大,但是思维难度还是有的qwq。
刚拿到这道题,我第一眼看过去还以为是积木大赛(是我瞎了,对不起)
但是,看到这道题,我们会想到使用差分,所以,我就试着用差分写一下。然后,好像就过了(震惊.jpg)
下面就来说一下这道题。
首先,我们得到这个数列之后先将这个数列进行差分,得到差分数组b[1]~b[n+1]
我们再来考虑一下本题目的要求,使我们得到完全一致的数列,那么转换到差分数组来说,就是2~n全部为0。
所以,我们的每一次修改对于差分数组来说,就只会修改两个数
操作1:修改b[i],b[j](2≤i,j≤n)这步操作对于一正一负的操作十分有效。
操作2: 修改b[1],b[i]这步操作对于正数变为0进行有效操作。
操作3: 修改b[i],b[n+1]这步操作对于负数变为0进行有效操作。
操作4:修改b[1],b[n+1],此操作无效,并没有对数列产生有效影响。
所以,当我们梳理完可以对于差分数组的所有有效操作后,我们就可以很简单的得出答案。
我们要统计b[2]~b[n]中间正数的和sumz,负数的和sumf
如果对于sumf和sumz我们要尽可能多的进行操作1,对于剩余的进行操作2、3,即可。又因为每一次操作2、3,对于b[1]的影响不同,所以方案数不同。
操作次数:max(sumf,sumz)
方案数: |sumf-sumz|+1
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1e5+7;
int b[N],a[N],n;
long long sumz,sumf;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i]-a[i-1];
}
// b[n+1]=0;
for(int i=2;i<=n;i++){
if(b[i]>0)sumz+=b[i];
else sumf+=b[i];
}
sumf*=-1;
// printf("%lld %lld\n",sumz,sumf);
printf("%lld\n",max(sumz,sumf));
printf("%lld\n",abs(sumz-sumf)+1);
}
这道题是一道差分好题,比较考验思维。