差分定义及基础性质

在做洛谷P2367语文成绩这道题的时候,发现用的就是一些差分的基础知识,于是乎就心血来潮写下了这篇文章

一、什么是差分

差分,先从这个词的构成角度来看,应该是与两数之差以及分块思想有关。
让我们先给定一个简单数列:

arr[1] = 1;
arr[2] = 2;
arr[3] = 4;

那我们的差分是怎么定义的呢,且看:

//d数组记录的就是差分
d[1] = arr[1] = 1;
d[2] = arr[2] - arr[1] = 1;
d[3] = arr[3] - arr[2] = 2;
d[4] = 0 - arr[3] = -4;

显而易见,差分数组 d 记录的就是数列中一个数和它前面的那个数之差

二、差分的一些基本性质

现在我们已经知道了差分的定义,那差分能用来干什么呢?
其实差分大部分情况都是用来解决一些对区间操作的问题的。
所以接下来,我们先来看第一个基本性质:

性质1:将原序列区间[L,R]中的元素全部 + k,可以转化操作为差分序列L处 + k,R+1处 - k。
如对上述序列区间[2,3]每个数加1,即:
arr[2] = 3; arr[3] = 5;
再看差分数组d
d[2] = arr[2] - arr[1] = 2; d[4] = 0 - arr[3] = -5;
对比原来的差分数组d,想必此条重要的性质就很清楚了吧。

再看看另外一个简单的性质:
性质2:差分序列求前缀和可得原序列
先说一下前缀和是什么。
前缀和,顾名思义,即一段序列的前 i 项之和。 其实就类似于数列的前n项和。
定义数组 s 保存上述差分数列的前缀和。

s[1] = d[1] = 1;
s[2] = d[2] + d[1] = 2;
s[3] = d[3] + d[2] + d[1] = 4;

知道了前缀和的定义,再把差分数组的定义代入每个前缀和的式子中,我想这个性质就不难理解了。

有了基础知识,接下来我们就把这道题干掉吧。
题目:P2367语文成绩
代码:

#define  _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cmath>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#include <stack>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <fstream>
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define LNF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
const int maxn = 5000002;
int n, p, minn = INF, arr[maxn], d[maxn], s[maxn];

inline int read() {
	int x = 0, f = 1; char c = getchar();
	while (!isdigit(c)) { if (c == '-') f *= -1; c = getchar(); }
	while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
	return x * f;
}

inline void put(int x) {
	if (x < 0) x = -x;
	if (x > 9) put(x / 10);
	putchar(x % 10 + '0');
}

int main() {
	n = read(), p = read();
	d[1] = arr[1] = read();
	for (int i = 2; i <= n; i++) {
		arr[i] = read();
		d[i] = arr[i] - arr[i - 1];
	}
	for (int i = 1; i <= p; i++) {
		int x = read(), y = read(), z = read();
		d[x] += z;
		d[y + 1] -= z;
	}
	for (int i = 1; i <= n; i++) {
		arr[i] = arr[i - 1] + d[i];
		if (arr[i] < minn) minn = arr[i];
	}
	put(minn);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>