(P3406 海底高铁)差分数组的应用

差分数组就是 两项的差值组成的数组。


int a[10] = {1,2,3,4,5,6,7,8,9}; // 差分数组 

int c[10] = {1,3,5,9,14,20,27,35,44}; //原数组 

差分数组与原数组相当于是逆运算。
a数组的前缀和就是c数组
c数组 a[i] = c[i] - c[i-1]; 前缀和数组的差分就是a数组他们是可以自由转换的。

差分数组描述的是每项之间大小的关系,就是第i项比第i-1项大多少。

区间修改
如果要求修改一个区间[l, r] 中元素的值,如全部加上一个x
则让差分数组c[l] + x, c[r] - x; 这样就让l后面差分数组上升x 然后让r后面的差分数组下降x,这样就维护了[l ,r] 区间差分的关系, 然后差分数组的前缀和就反应了 a[i] 的大小, 这样如果需要大量跟新区间元素时,可以利用差分数组跟新,然后再最后需要使用a数组的时候,计算前缀合,然后就可以得到每个点元素的大小了
数组的每两项的差值描述了, 该数组相邻两两元素的大小关系, 即知道第一个元素就可以通过差分数组计算出整个数组, 也就是前缀和。
a[i] = a[i-1] + c[i] // a[i] 比 a[i-1] 大 c[i]
c[i] = a[i] - a[i-1] // 差分数组与前缀和数组逆运算
[P3406 海底高铁]
差分练习题

#include<string>
#include<iostream>
#define ll long long
using namespace std;
const int maxn = 100010;
ll a[maxn];
ll c[maxn];
int n, k;
ll p[maxn][3];
long long ans = 0;
long long temp = 0;
inline void add(int x, int y) { //区间修改
	c[x]++;
	c[y+1]--;
}
int main() {
	scanf("%d%d", &n, &k);
	int pre;
	scanf("%d", &pre);
	for(int i = 1; i < k; i++) {
		int t;
		scanf("%d", &t);
		if(pre < t) add(pre, t - 1);
		else add(t, pre - 1);
		pre = t;
		//scanf("%d", &order[i]);
	}
	for(int i = 1; i <= n-1; i++) {
		scanf("%d%d%d", &p[i][0], &p[i][1], &p[i][2]);
	}
	for(int i = 1; i <= n; i++) {
		c[i] += c[i-1]; //计算前缀和,差分数组转化为前缀和数组,前缀和数组的每个点就是区间中的点值
	//	printf("%d ", c[i]);
	}
	for(int i = 1; i < n; i++) { //计算每条地铁的花费
		ll card, notCard;
		notCard = c[i] * p[i][0];
		card = (c[i]) * p[i][1] + p[i][2];
		ans += min(notCard, card);
	}
	printf("%lld", ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值