题目链接:This is link
题目大意:
给你一个长度为 n n n 的序列 a a a,每次可以进行一下三种操作的任意一种
- 选择 i i i,使得 a 1 , a 2 , a 3 , … , a i a_1,a_2,a_3,…,a_i a1,a2,a3,…,ai 减 1.
- 选择 i i i,使得 a i , a i + 1 , a i + 2 , … , a n a_i,a_{i+1},a_{i+2},…,a_n ai,ai+1,ai+2,…,an 减 1.
- 将序列中的每个数加 1.
求将序列 a a a中的每个元素变为1的最小操作次数。
解题思路:
通过操作1和操作2我们可知它是对序列的左右区间是有影响的,而操作3是对整个序列是有影响的。并且我们发现当序列是单调递增的时候,我们可以很容易的求出来操作次数。
例如: 5 5 6 8 9 将此序列全部变成0的最小操作次数为9次,即只选择操作二即可,选择的下标为 :1,1,1,1,1,3,4,4,5。所以我们很容易发现当序列是单调递增且 a 1 ≥ 0 a_1 ≥ 0 a1≥0的时候,操作次数为 a n a_n an. 所以我们不妨去构造这样的一个序列,进而求取最小操作次数。
那么该怎么去构造呢?我们可以从后到前枚举每一个元素,如果当前元素大于后面相邻元素,我们可以通过操作一 (
a
i
−
a
i
+
1
a_i -a_{i+1}
ai−ai+1)次来让当前元素等于后面相邻元素,直至枚举完第一个元素。
举个例子:4 -4 4 -4
- 首先a[3] > a[4] ,我们通过操作一 ( a[3] - a[4] )次使得序列变成: -4 -12 -4 -4
- 然后a[2] < a[3] ,跳过即可
- 又因为a[1] > a[2] ,我们通过操作一( a[1] - a[2] )次使得序列变成:-12 -12 -4 -4
- 此时我们已经使得序列成为了一个单调递增的序列,但是我们发现 a 1 a_1 a1是小于 0 0 0的,所以我们需要通过操作三12次使得序列成为:0 0 8 8 ,这样才构造出来了我么所需要的序列。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
int a[N];
int main()
{
int t; cin >> t;
while (t--)
{
int n; cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
ll ans = 0;
for (int i = n - 1; i >= 1; i--)
{
if (a[i] > a[i + 1]) ans += a[i] - a[i + 1];
}
if (a[1] - ans >= 0) cout << ans + a[n] << endl;
else cout << ans + (ans - a[1]) * 2 + a[n] << endl;
}
return 0;
}