题目分析
直接贴一个洛谷上的题解,真的秀,讲的又清楚又好
要使得序列的数全部相等,其实就是让他们之间的差全为0,也就是差分序列的除了第一项每一项都是0,为什么除了第一项呢,因为b[1]=a[1]-a[0],而a[1]是开头的数
我们把问题转化成了让差分序列除第一项全等于0之后,继续思考
由于题目要求最少的步骤,我们可以考虑,如果差分序列里有一个正数和一个负数(出现的顺序无所谓),那么我们优先对这个正数和负数进行操作,为什么呢?因为我们有以下两个公式
如果a[l,r]+1,则b[l]+1,b[r+1]-1
如果a[l,r]-1,则b[l]-1,b[r+1]+1
正数-1,负数+1,这样相当于一步里作用了两步,比让正数一个个-1和让负数一个个+1快多了
那么我们可以进行多少种这样的操作呢?
我们可以令差分序列里正数绝对值的总和为p,负数绝对值总和为q
可以进行这样一步顶两步的操作就是min(p,q),因为这种操作正数负数是一一配对的,当少的那个先用完了,剩下的没有可以配对的了,只能一步步减或一步步加。
所以我们总共要进行的操作就为min(p,q)+abs(p-q),也就是max(p,q)
第一问完成,看第二问
保证最少次数的前提下,最终得到的数列有多少种?
得到的数列有多少种,其实就是问的b[1]可以有多少种
我们上述所有操作是与b[1]无关的,因为我们的目标是让除了b[1]以外的项变0,所以我们上述的操作没有考虑到b[1],b[1]怎么变,与我们求出的最小步骤无关
那么,我们怎么知道b[1]有几种呢?很简单,其实就是看看有几种一步步减或一步步加的操作数,因为我们一步步加的时候(假设我们现在的操作对象下标为i),可以这样操作,b[1]-1,b[i]+1一步步减的时候可以这样操作,b[1]+1,b[i]-1(注意,一个差分序列里一步步操作的时候只可能一步步加或一步步减,不可能一步步加和一步步减同时存在)
所以说,有几步一步步的操作就有几种情况+1,为什么+1呢,因为这个b[1]本身就有一个值啊!就算你不对他进行任何操作,它自己也有一种情况。
一加一减(也就是我们所说的一步顶两步的操作)操作数为min(p,q)
那么一步步的操作数就为max(p,q)-min(p,q)=abs(p,q)
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
long long a[N], d[N], p, q;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> a[i];
d[i] += a[i];
d[i + 1] -= a[i];
}
for (int i = 2; i <= n; i ++ )
{
if (d[i] > 0) p += d[i];
else if (d[i] < 0) q -= d[i];
}
// cout << min(p - q) + abs(p - q) << endl << abs(p - q) + 1 << endl;
cout << max(p, q) <<endl << abs(p - q) + 1 << endl;
return 0;
}
标签:洛谷,Sequence,int,一步步,P4552,差分,负数,操作,正数
From: https://www.cnblogs.com/Panmaru/p/16939594.html