差分: 模板+题目
题目:【模板】差分
应用场景:快速解决将某一个区间所有元素加上 “一个数” 的操作。
第一步,预处理差分数组。
f[i] 表示:当前元素与前一个元素的差值 a[i] - a[i-1];
但在题目中,我们其实可以不用到a[]这个数组,只使用f[]数组。我们可以先减后加:(易错)
LL x; cin >> x;f[i+1] -= x; //可以不用创建a[],直接使用f[] 先减后加f[i] += x;
第二步,利用差分数组解决m次修改操作
第三步,如何还原数组?
直接对差分数组做前缀和运算即可。(前面的数变大,后面的数加上前面的数自然会变大)
#include <iostream>using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
LL f[N]; int n, m; int main()
{cin >> n >> m;//有几个数,有m次操作for (int i = 1; i <= n; i++){LL x; cin >> x;f[i+1] -= x; //可以不用创建a[]: 先减后加f[i] += x;}while(m--){LL l, r, k; cin >> l >> r >> k;f[l] += k; f[r+1] -= k;} for (int i = 1; i <= n; i++){f[i] = f[i-1] + f[i];cout << f[i] << " ";}return 0;
}
题目:P3406 海底高铁 - 洛谷
#include <iostream>using namespace std;
const int N = 1e6 + 10;
typedef long long LL;LL f[N];
int n, m;
LL sum = 0;//第二段铁路连接城市2-3 ,每次单独购买车票
//花Ci买卡,乘坐只要扣给Bi元 //N,M 表示N个城市,N-1段铁路 要访问M个城市
//M个要访问的城市
//N-1个单独车票,买卡,买卡票 int main()
{cin >> n >> m;int x; cin >> x;int y;for (int i = 2; i <= m; i++){cin >> y;if (x > y){f[y]++;f[x]--;}else{f[y]--;f[x]++;}x = y;}for (int i = 1; i <= n; i++){f[i+1] += f[i];}for (int i = 1; i < n; i++){LL a, b, c; cin >> a >> b >> c;sum += min(f[i]*a, c+f[i]*b);}cout << sum << endl; return 0;
}