差分的题目

一道关于差分的题目

田小锋有n个盒子,这个B想要在这n个盒子放入一定量的球。一开始n个盒子是空的,接下来每次操作,这个B可以选择一段连续区间[L,R],然后在第L个盒子到第R个盒子之间每个盒子都放入一个球(含第L个和第R个玻璃瓶),求能达到符合的要求的最少的操作次数。

输入格式:
第一行包含一个整数 n(1≤n≤110),表示n个盒子。 
第二行包含 n 个整数,表示每个盒子要求要放的球个数m。 0≤m≤10000

输出格式:
仅一行,即所需的最少操作数。

输入样例:
5
2 3 4 1 2

输出样例:
5
(解释:
    操作1[1,5]区间放一个
    操作2[1,3]区间放一个
    操作3[2,3]区间放一个
    操作4[3,3]区间放一个
    操作5[5,5]区间放一个,放的方法不唯一,但是最少操作次数是5次)

思路:差分

这个是样例的数据:

在这里插入图片描述

下面只看下标1-5的

最开始的时候全部的盒子都是空的,即差分数组元素全部都是0。那么我们反过来推导,让上图中的差分数组经过操作全部变成0.

重要的一点:此题中差分数组正数之和是绝对大于等于负数之和的,为什么呢?因为差分数组的前缀和数组就是hezi数组里面的元素值,盒子里面的球的个数是>=0的,这样一来,此题中差分数组正数之和是绝对大于等于负数之和的

对区间[L,R]操作全部加一或者减一,对应的差分数组就是c[L]+(-)1,c[R+1]-(+)1。这个应该不用多说。

我们再来看差分数组:2 1 1 -3 1. 最少操作次数让它全部变成0,前面加一,对应的后面就要减一,反之亦然。又因为此题中差分数组正数之和是绝对大于等于负数之和的,我们可以让负数和正数抵消掉,每次抵消1也算作一次操作,所以我们只算出差分数组中正数之和就行了。

上图中,2,1可以和-3抵消,剩下的数组元素就是0 0 1 0 1,(对应的盒子中就是0 0 1 1 2),然后[3,5]减一,由于5+1超界了,就不算了呗,所以[3,5]减一后就是0 0 0 0 1(盒子中0 0 0 0 1),然后[5,5]减一,最后变成了0 0 0 0 0就行了,所以差分数组中剩下的全部是正数的时候,我们就[L,N]区间来操作,N是数组最大的下标。最后总结看就是把正数加起来就行了嘛。

#include <iostream>

using namespace std;
const int N = 1e5+5;
int num[N], n, ans = 0, c[N];

int main()
{
	cin >> n;
	for ( int i = 1; i <= n; ++i ) {
		cin >> num[i];
		c[i] = num[i] - num[i-1];
	}
	
//	for ( int i = 1; i <= n; ++i ) {
//		cout << c[i] << " ";
//	}
//	cout << '\n';
	
	for ( int i = 1; i <= n; ++i ) {
		ans += c[i] >= 0 ? c[i] : 0;
	}
	
	cout << ans << endl;
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值