差分基本概念
a[1],a[2],.…a[n]
b[i]=a[i]-a[i-1],b[1]=a[1]
a[i]=b[1]+b[2]+.…+b[i]
=a[1]+a[2]-a[1]+a[3]-a[2]+.…+a[i]-a[i-1]
由此可见,原数组就是差分数组的前缀和。我们可以举个例子:
原始数组:9 3 6 2 6 8
差分数组:9 -6 3 -4 4 2
现在有一个任务,在区间$[l,r]$上加一个常数c。
我们可以利用原数组就是差分数组的前缀和这个特性,来解决这个问题。显然可得出公式:$b[l] += c,b[r + 1] -= c$ 。
例2IncDec序列
给定一个长度为 $n$ 的数列 $a1,a2,…,an$,每次可以选择一个区间 $[l,r]$,使下标在这个区间内的数都加一或者都减一。
求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。
输入格式
第一行输入正整数$n$。
接下来$n$行,每行输入一个整数,第$i+1$行的整数代表$ai$。
输出格式
第一行输出最少操作次数。
第二行输出最终能得到多少种结果。
数据范围
$0<n≤10^5$,
$0≤ai<2147483648$
输入样例:
4
1
1
2
2
输出样例:
1
2
题解:
要使最后的数都一样,那么$b$数组中的$b2=>bn$ 一定全 $0$
因为
b2 = a2-a1;
b3 = a3-a2;
......
bn = an-an-1;
如果全0 的话, $a1=a2=a3=…=an$
所以我们可以用贪心的思想,来使得b中所有数变成零。 我们知道我们在做b[L]++,b[R+1]--
;操作的时候,要找两个数配对,那么 负数++
,正数--
,是不是就最快了。 但是最终结果可能依然不是全 $0$ 的,因为 $abs(sum(正数)) 可能 != abs(sum(负数))$
所以,我们可以 让最后不等于0 的数全和 $b1|| bn+1$来换。
$ans1 = min(pos,neg)+abs(pos-neg)$
$ans2 = abs(pos-neg)+1$
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int num[maxn];
inline void init()
{
int n = 0;
cin >> n;
for(int i = 1;i <= n;++i)
cin >> num[i];
for(int i = n;i > 1;--i)
num[i] -= num[i-1];
}
inline void frond()
{
long long pos = 0,neg = 0;
for(int i = 2;i <= n;++i)
{
if(a[i] > 0) pos += a[i];
else neg -= a[i];
}
cout << min(pos,neg) + abs(pos - neg) << endl << abs(pos - neg) + 1;
}
int main(void)
{
init();
frond();
return 0;
}
你好棒
大佬们,为啥剩余的是abs(p - q) 个呢?假如差分数列未1,-3, 4, -2, 5, -7那我先把所有正数变为0然后数列为
1, -3, 0, -2, 0, -7按结论是说还需要操作abs(p - q) == 3次,可是操作3次并不能把他们变为全0数列啊
$$ p = 9, q = -12, min(q, abs(p)) = 9, abs(p-abs(q)) = 3 \\ 所需次数=min(q, abs(p)) + abs(p-abs(q)) = max(q, abs(p)) = 12 $$
原差分序列1 -3 4 -2 5 -7
所以根据解法先操作9次操作1
最后3次操作用操作2和操作3结合将-3变成0
你这个序列需要12次,9次操作1,剩下的3次给操作2与操作3不同方式分配
道理我都懂, 但我有个问题, 这代码能跑吗
当然了 建议凑一下空类型 不用返回
666
ans1=min(pos,neg)+abs(pos−neg)这里就是max(pos,neg);没必要多此一举了
但是按解题的思路应该是最小值加上其差值 虽然从结果上和max是一样的。。 但是做题不会一下就想到max
数组1-n
b1=a2-a1;
......
那么bn+1代表什么呢
差分数组 b1=a1
b2=a2-a1
大佬我有一个疑问为什么我把min(pos,neg)替换为neg不行neg不是<=0而pos不是>=0吗?为什么替换会报错呢?
if(a[i] > 0) pos += a[i]; else neg -= a[i];
pos 正数绝对值之和
neg 负数绝对值之和
老哥,你这个数组有两个变量名a和num,建议改下
用滚动数组优化一下空间
提供一个常数空间的答案:
更好的阅读体验