# 差分

***

差分是前缀和的逆运算。

差分数列，由该位置元素和前一个元素的差构成。

> 例子：
>
> 2 3 5 7 11 13 17 19
>
> 差分数列：2 1 2 2 4 2 4 2

### 作用：

用于将区间操作转换成单点操作，原本对区间的操作在差分数列上体现的是对1-2个单点的操作。

例如，对数列的前k项同时-1，差分数列上表现为对第1项减1，对第n+1项加1，其余项不变。

### 例题：

[Problem - D - Codeforces](https://codeforces.com/contest/1443/problem/D)

题意：给定一串序列，可以进行无限次操作：对前任意k个数减1或对后任意k个数减1，求是否能将这个数组的元素全部置0.

发现是前k个和后k个的区间问题，考虑维护差分，把原数列置零等同于把差分数列置零（第一项是0，剩下的项和第一项的差都是0）。

对差分数列来说，对前k个数减1只意味着对第1项减1，对第n+1项加1，其余项不变；对后k个数减1对差分数列只意味着对第k项减1。

容易发现，我们可以对任意正数做任意次减1，直到减到0为止；唯一的变数在于负数，某负数要加到0，只能靠减第一项来实现。所以只用判断第一项减到0时负数能不能都加到0就行了。

代码：

```
const int maxn = 30005;
int a[maxn],dif[maxn];
int main() {
	int t;
	cin >> t;
	while (t--) {
		int n; cin >> n;
		for (int i = 1; i <= n; i++) cin >> a[i];
		dif[1] = a[1];
		int tot = 0;
		for (int i = 2; i <= n; i++) {
			dif[i] = a[i] - a[i - 1];
			if (dif[i] < 0) tot-=dif[i];
		}
		if (a[1] >= tot) cout << "YES\n";
		else cout << "NO\n";
	}
}
```
