[Acwing] 100. 增减序列 差分

前言

好难的一题
传送门 :

前言

对于差分操作,如果一个区间加上一个常数c: 如下
d [ l ] + = c     ,     d [ r ] − = c     ( d 为 差 分 数 组 ) d[l]+=c\ \ \ , \ \ \ d[r]-=c \ \ \ (d为差分数组) d[l]+=c   ,   d[r]=c   (d)

如果一个数组所有数都一样也就是说明差分数组为0

又因为 :
b [ 1 ] = a [ 1 ] , b [ 2 ] = a [ 2 ] − a [ 1 ] , b [ 3 ] = a [ 3 ] − a [ 2 ] . . . . . b[1] = a[1],b[2]=a[2]-a[1],b[3]=a[3]-a[2]..... b[1]=a[1],b[2]=a[2]a[1],b[3]=a[3]a[2].....

因此这个题目可以转换为, 从 [ 2 − n ] [2-n] [2n]选出两个数,一个 + 1 +1 +1,一个 − 1 -1 1,使得 b [ 2.. n ] = 0 b[2..n] = 0 b[2..n]=0

这样子数组就变为了 n n n a [ 1 ] a[1] a[1] , 这样子显然的我们尽可能需选出 b [ l ] ∗ b [ r ] < 0 b[l]*b[r]<0 b[l]b[r]<0

因为这样子才可以让每次操作都有意义,所以对于如下操作有一下几种操作

  • 2 < = l , r < = n 2<=l,r<=n 2<=l,r<=n
  • l = 1 , 2 < = r < = n l=1,2<=r<=n l=1,2<=r<=n
  • 2 < = l < = n , r = n + 1 2<=l<=n,r =n+1 2<=l<=n,r=n+1
  • l = 1 , r = n + 1 l = 1, r =n+1 l=1,r=n+1(没意义,显然的)

为什么会出现中间两种呢 ? 因为如果数组中的 s u m ( b [ i ] > 0 ) ! = s u m ( b [ i ] < 0 ) sum(b[i]>0) != sum(b[i]<0) sum(b[i]>0)!=sum(b[i]<0),

那么我们只能,对 1 ∣ ∣ n + 1 1||n+1 1n+1进行操作,使得我们的操作可以进行下去

因为最小的操作次数 = m i n ( s 1 , s 2 ) + a b s ( s 1 − s 2 ) min(s1,s2) + abs(s1-s2) min(s1,s2)+abs(s1s2)

因为数组最后都是 a [ 1 ] a[1] a[1],所以也就是询问 a [ 1 ] a[1] a[1]的可能值

所以种类数= a b s ( s 2 − s 1 ) + 1 abs(s2-s1)+1 abs(s2s1)+1


当然一开始我是没想到的,直接口胡了一个答案,虽然样例过了但是爆 L L LL LL

CODE

const int N  = 1e5+10;
int a[N],d[N];
int  n;

void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		d[i] = a[i] - a[i-1];
	}
	

	ll  p = 0 ,q = 0 ;
	
	for(int i=2;i<=n;i++){
		if(d[i]>0)
		p+=d[i];
		else
		q-=d[i];
	}
	
	cout<<min(p,q)+abs(p-q)<<endl;
	cout<<abs(p-q)+1<<endl;
	
	
	
}
signed main()
{
    //int t;cin>>t;while(t -- )
    solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值