题意
给定一个长度为\(n\)的序列\(t\),每次操作可以将连续一段全部加上\(1\)或者减去\(1\)。给定另外一个长度为\(n\)的序列\(p\),问最少操作多少次,可以将序列\(t\)变为序列\(p\)。
数据范围
\(1 \leq n \leq 10^5\)
思路
将两个序列逐元素作差,问题就转化为了进行若干次操作,将该序列所有元素变为\(0\)。
将该序列差分,于是每个操作相当于将:
- 一个元素加\(1\),一个元素减\(1\)
- 一个元素加\(1\)
- 一个元素减\(1\)
所以,最终结果为所有负数求和与所有正数求和的绝对值的最大值。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int p[N], t[N];
int b[N];
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &p[i]);
for(int i = 1; i <= n; i ++) scanf("%d", &t[i]);
for(int i = 1; i <= n; i ++) p[i] -= t[i];
for(int i = 1; i <= n; i ++) {
b[i] = p[i] - p[i - 1];
}
int neg = 0, pos = 0;
for(int i = 1; i <= n; i ++) {
if(b[i] < 0) neg -= b[i];
else pos += b[i];
}
printf("%d\n", max(neg, pos));
return 0;
}