传送门
题意:有n栋楼,每栋楼的高度为,对美丽的楼的定义如下:
对于,如果并且,那么就说明这栋楼是美丽的。(所以第一栋楼和最后一栋一定不是美丽的)
lk现在可以将所有的楼的高度增加任意值,他想知道他能获得的最多的美丽的楼的前提下花费最小为多少。
思路:
首先对于2-n 的下标进行处理,如果将该栋楼变成美丽的就视为1,否则视为0.
预处理v数组算出将栋楼变成美丽楼的代价,
n为奇数的话,因为只有一种可能的情况,就是1010101....,直接算出所有要变成的美丽楼的代价。
如果n为偶数:假设n为8的情况,去掉第一个和最后一个,我们可以直接求出所有的规律:
//101010
//101001
//100101
//010101
那么我们可以发现,对于后面是10 的,那么前面一定不能变成01,那么对于有01的情况,一定是从末尾开始变,一直变到第一个。
那么可以直接先计算出全部为10的结果,然后每次将后面的10转换成01然后取最小值,最后的结果就是我们的答案。
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=100100+100;
const ll INF=1e18;
int n ,m,h;
ll s[N];
ll v[N];
int main()
{
int t;
sc_int(t);
while(t--)
{
sc_int(n);
memset(v,0,sizeof v);
for(int i =1;i<=n;i++)
sc_ll(s[i]);
if(n%2!=0){
ll res=0;
for(int i=2;i<=n;i+=2)
if(s[i]<=max(s[i-1],s[i+1]))res+=max(s[i-1],s[i+1])-s[i]+1;
pr_ll_n(res);
}
else{
ll res=INF,sum=0;
for(int i =2;i<n;i++){
if(s[i]<=max(s[i-1],s[i+1]))v[i]=max(s[i-1],s[i+1])-s[i]+1;
if(i%2==0)sum+=v[i];
}
// for(int i =2;i<n;i++)
// cout<<v[i]<<" ";
// cout<<endl;
res=min(res,sum);//12 1000000000 1 1 1000000000 999800701 2 600700800 900000000 500600700 1 500700900 1000000000
for(int i =n-1;i>2;i-=2) // 1 2 3 4 5 6
{
sum-=v[i-1];
sum+=v[i];
res=min(res,sum);
}
pr_ll_n(res);
}
}
return 0;
}