感谢@海绵宝宝 大佬指出本文的一个错误,万分感谢啊!
话说这么多大佬都看了,为啥没有康出来呢。
题目描述
给定一个长度为 n 的数列 $a_1,a_2,…,a_n$,每次可以选择一个区间 $[l,r]$,使下标在这个区间内的数都加一或者都减一。
求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。
输入格式
第一行输入正整数n。
接下来n行,每行输入一个整数,第i+1行的整数代表ai。
输出格式
第一行输出最少操作次数。
第二行输出最终能得到多少种结果。
数据范围
$0<n≤10^5$
$0≤a_i<2147483648$
输入样例:
4
1
1
2
2
输出样例:
1
2
算法分析:差分+贪心
思路:首先这题一个重点,就是区间$[l,r]$的修改操作。因为这道题目的修改操作有一个特性,就是只加一或者只减一,而不是$+x$,也不是$-x$,所以说我们并不需要用到高级的数据结构,线段树和树状数组,而只是需要用差分即可。
差分:差分的定义,可以见《算法竞赛进阶指南》的P21页。
介于第一版没有差分,这里说一下定义:对于一个给定的数列A,它的差分数列B定义为, $ B[1]=A[1],B[i]=A_i−A_{i−1} (2<=i<=n) $
这里只说性质,也就是把序列A的区间$[L,R]$加d,也就是把$A_l,A_{l+1}....A_r$都加上d,其实就是它的差分序列B中,$B_l+d,B_{r+1}-d$,其他的位置统统不改变。
因此在这道题目中,我们就可以利用这个非常有用的性质,因为我们只要求A序列中所有的数相同,而不在意这些方案具体是什么,所以说我们就可以转化题目,也就是将对A序列的$+1,-1$操作,让A序列相同,改成目标把$B_2,…,B_n$变成全0即可,也就是A序列全部相等。而且最后得到的序列,就是这n个$B_1$
贪心:因为我们有上面所说的性质,那么我们就可以,每一次选取$B_i和B_j$,$ 2<=i,j<=n $,而且这两个数,一个为正数,一个为负数,至于为什么要是正负配对,因为我们是要这个B序列2~n都要为0,所以这样负数增加,正数减少,就可以最快地到达目标为0的状态。
至于那些无法配对的数$B_k$可以选$B_1$或者$B_n+1$,这两个不影响的数,进行修改。
所以说我们这道题目得出的答案就是,最少操作数$min(p,q)+abs(p-q)=max(p,q) $,然后最终序列a可能会有$abs(p-q)+1$种情况。$p为b序列中正数之和,而q为b序列中负数之和$
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 110000
ll n,m,i,j,p,q,a[N];
int main()
{
scanf("%lld",&n);
for (i=1;i<=n;i++)
scanf("%lld",&a[i]);
for (i=2;i<=n;i++)
{
ll c=a[i]-a[i-1];
if (c>0)//不要输入 if (c) 因为c是指不为0就好了,如果c为-1,那么最后的布尔值也为1,if(c)的意思是,只要c不为0,那么条件的布尔值都为1
p+=c;
else
q-=c;
}
ll ans1=max(p,q),ans2=abs(p-q)+1;
cout<<ans1<<endl<<ans2;
return 0;
}
为什么种类数是|(|p| - |q|)| + 1呢?本小菜鸡确实没有看懂。
注意啦!注意啦!必须要开long long!本蒟蒻已经被坑过一次了!
在差分数组中bn+1=an+1-an 但是数组大小总共才为n 那么这个bn+1代表什么呢
求解答
b[n+1]-1其实并没有含义。因为当我们需要对区间[i,n]所有a_n执行+1操作时,只需要b[i]+1就可完成,a[n+1]以及后面的数是没有定义的,所以b[n+1]-1这一步恢复也就没有实际含义。
估计是为了统一公式
兄弟是蓝桥杯吧,加油
使数列中所有的数都一样,也可以是都和a[2]相等吧?
对,数列中第一个数可以更改
大佬们,为啥剩余的是abs(p - q) 个呢?假如差分数列未1,-3, 4, -2, 5, -7那我先把所有正数变为0然后数列为
1, -3, 0, -2, 0, -7按结论是说还需要操作abs(p - q) == 3次,可是操作3次并不能把他们变为全0数列啊
你的例子是这样的吗?b1=1,b2=-3,b3=4,b4=-2,b5=-7,因为我们要求的是让a数组全部相同,那么就是a1=a2=a3=…=an,由于b[n]=a[n]-a[n-1],那我们只需要b2=b3=b4=…=bn=0就行,所以不需要b1也等于0,因为b2已经让a1=a2了,所以,我们先求出pos=9(不需要考虑b1,因为我们的操作只需要让b2=b3=b4=…=bn=0),neg=12,那么min取9,即先使负数+1,正数-1,操作9次,比如操作后的结果为1,-3,0,0,0,0(结果什么样无所谓,主要是最后我们发现多了-3),这个-3可以通过b1,和bj(2<=j<=n)操作,比如这个例子里可以选b1和b2,用-1操作3次,那么b1最后+(-1)3,为-2,b2最后-(-1)3为0,这样就结束了,操作次数为12满足公式,当然,选择方案还可以用bn+1,和前面的bi替换。
我想的可能不对,如果有带佬看出来错误,请教教我哈哈
差分为什么不能进行区间的+x,-x操作呢,不就是+1-1变成+x-x不就行了吗
好家伙,你连题目要求都要该是吧,
看你解析终于懂了,呜呜呜,太强了
%%%
为什么要开longlong?
不开longlong容易爆
不开longlong溢出
赞!浅显易懂!
哪位大佬跟我解释一下结果种类数是咋来的我看了好久还是不明白。
就是那个较小的操作完了,还有较大的数字没有操作 假如现在有还有abs(p-q)=5;就是还有5没有清零可能有 0 5
5 0 1 4 4 1 2 3 3 2 这六种就是数字加一
请问这里为什么会有abs(p−q)+1种结果呢?
因为0是一种,所以要+1
p~q都可以的.
什么p~q都可以,具体说下, 可以么
就是最终得到的序列a可能有abs(p-q+1)种
oo
+1要放在外面吧
还是没懂为什么
是的,我打错了
%%%
为什么调试的时候输出和答案不同 最后也能 AC 啊
同问
q指的是差分数组的负值之和的绝对值哦
为什么 要 +1 abs (p−q)+1abs(p−q)+1
因为如果剩下3个数没有处理掉那么左边有0 1 2 3 对应的右边 3 2 1 0 一共是3+1也就是abs(p-q)+1种可能哦
大佬如果这个题,每次只能操作一个数,而不是一个区间,该怎么做
都搞成中位数吧,绝对值不等式应该可以证明这个策略是最优的。
555555,巨佬不鸟我
看看这个 大佬暂退了啦~
你好,可以解释一下b1为什么无影响吗,我想了很久,没有想通,y总的视频也看了几遍,仍然无法理解
只要保证了,B[2]~B[n]都为0,就意味着每个数都和A[1]相等了,所以不管B1是多少都无所谓
可是这个思路算下来,所有的数都和a1相等了,那其他的选择呢?比如说所有的数和a2,or a3, or a4 … or an相等?
tql
woc,蒸
至于那些无法配对的数BkBk可以选B1B1或者BnBn,这两个不影响的数,进行修改。
这里是Bn+1吧?
是的,我打错了。感谢大佬指出问题!