第三题:BALANCING BACTERIA
标签:思维、差分
题意:给定 n n n个数, a 1 , a 2 , a 3 . . . a n a_1,a_2,a_3...a_n a1,a2,a3...an,每次操作 可以选择数字 L ( 1 < = L < = n ) L(1<=L<=n) L(1<=L<=n),并选择增加或者减少。
比如增加的情况,从第 n n n个数开始,第 n n n个数增加 L L L,第 n − 1 n-1 n−1个数增加 L − 1 L-1 L−1,第 n − 2 n-2 n−2个数增加 L − 2 L-2 L−2…,依次类推,直到增加值为 0 0 0,再往前就不增加(即第 1 1 1个到第 n − L n-L n−L个数不增加值)
求将所有数变成 0 0 0的最少操作次数。( 1 < = n < = 2 ∗ 1 0 5 , 1 0 − 15 < = a i < = 1 0 15 1<=n<=2*10^5,10^{-15}<=a_i<=10^{15} 1<=n<=2∗105,10−15<=ai<=1015)
举个例子:比如有两个数 − 1 3 -1\ \ \ 3 −1 3
可以先从选择数字 L = 1 L=1 L=1并进行减少,操作 5 5 5次,把序列变成: − 1 − 2 -1\ \ \ \ -2 −1 −2
然后选择数字 L = 2 L=2 L=2,并进行增加,操作 1 1 1次,把序列变成: 0 0 0\ \ \ 0 0 0。总共 6 6 6次操作。
题解:以样例 2 2 2为例,有 5 5 5个数: 1 3 − 2 − 7 5 1\ \ \ 3 \ \ -2 \ \ -7 \ \ \ 5 1 3 −2 −7 5
我们维护一个差分数组 b i b_i bi为 a i − a i − 1 a_i-a_{i-1} ai−ai−1: 1 2 − 5 − 5 12 1\ \ \ 2 \ \ -5 \ \ -5 \ \ \ 12 1 2 −5 −5 12
这个差分数组表示原 a a a数组中相邻两个数的差值,我们额外对 i = 1 i=1 i=1的时候求 b 1 = a 1 − a 0 b_1=a_1-a_0 b1=a1−a0, a 0 = 0 a_0=0 a0=0。
再对差分数组 b i b_i bi做差分, c i = b i − b i − 1 c_i=b_i-b_{i-1} ci=bi−bi−1: 1 1 − 7 0 17 1 \ \ 1 \ \ -7 \ \ 0 \ \ 17 1 1 −7 0 17
原 a i a_i ai: 1 3 − 2 − 7 5 1\ \ \ 3 \ \ -2 \ \ -7 \ \ \ 5 1 3 −2 −7 5
第 1 1 1轮 a i a_i ai: − 1 − 2 − 3 − 4 − 5 = > 0 1 − 5 − 11 0 -1\ -2\ -3\ -4 \ -5=> 0\ \ \ 1 \ \ -5 \ \ -11 \ \ \ 0 −1 −2 −3 −4 −5=>0 1 −5 −11 0 (操作次数 + 1 +1 +1)
第 2 2 2轮 a i a_i ai: 0 − 1 − 2 − 3 − 4 = > 0 0 − 7 − 14 − 4 0\ -1\ -2\ -3 \ -4=> 0\ \ \ 0 \ \ -7 \ \ -14 \ \ \ -4 0 −1 −2 −3 −4=>0 0 −7 −14 −4 (操作次数 + 1 +1 +1)
第 3 3 3轮 a i a_i ai: 0 0 1 2 3 = > 0 0 0 0 17 0\ 0\ 1\ 2 \ 3=> 0\ \ \ 0 \ \ 0 \ \ 0 \ \ \ 17 0 0 1 2 3=>0 0 0 0 17 (操作次数 + 7 +7 +7)
第 4 4 4轮 a i a_i ai: 0 0 0 0 0 = > 0 0 0 0 17 0\ 0\ 0\ 0 \ 0=> 0\ \ \ 0 \ \ 0 \ \ 0 \ \ \ 17 0 0 0 0 0=>0 0 0 0 17 (操作次数 + 0 +0 +0)
第 5 5 5轮 a i a_i ai: 0 0 0 0 − 1 = > 0 0 0 0 0 0\ 0\ 0\ 0 \ -1=> 0\ \ \ 0 \ \ 0 \ \ 0 \ \ \ 0 0 0 0 0 −1=>0 0 0 0 0 (操作次数 + 17 +17 +17)
我们能够发现每次归 0 0 0的操作次数就是对应 c i c_i ci的绝对值。其实就是对 b i b_i bi进行差分,得到每个对应的后缀需要修改多少。
代码:
#include <bits/stdc++.h>
using namespace std;const int N = 2e5 + 10;
typedef long long ll;
ll a[N], b[N], n, ans = 0;int main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];b[i] = a[i] - a[i - 1]; // 差分}for (int i = 1; i <= n; i++) {ans += abs(b[i] - b[i - 1]);}cout << ans << endl;return 0;
}