B. Blackslex and Showering
时间限制:每测试点 2 秒
内存限制:每测试点 256 兆字节
问题描述
在他的 IMO 奖牌得主朋友“为了这周不用再洗澡”而洗了两个小时澡之后,Blackslex 要上课迟到了!
为了去上课,Blackslex 必须按照特定顺序乘坐拥挤的电梯前往许多楼层。因为他是一名黑客,他可以在其他人不知情的情况下跳过访问至多一个楼层。他所花费的时间是连续楼层号之间绝对差值的总和。在允许跳过至多一个楼层的情况下,求所需的最小时间。
更正式地说,给定一个包含 n 个整数的数组 a=[a_1, a_2, \dots, a_n],你可以选择至多一个索引 k \in \{1, 2, \dots, n\} 来删除元素 a_k,使得和式 $$ \sum_{i=1}^{n-2} |b_i - b_{i+1}| $$ 最小化,其中 b=[a_1, \dots, a_{k-1}, a_{k+1}, \dots, a_n] 是删除元素 a_k 后的数组。请输出这个最小和。
输入格式
第一行包含一个整数 t (1 \le t \le 10^4) —— 测试用例的数量。
每个测试用例的第一行包含一个整数 n (3 \le n \le 2 \cdot 10^5) —— 数组的大小。
第二行包含 n 个整数 a_1, a_2, \dots, a_n (1 \le a_i \le 100)。
保证所有测试用例的 n 之和不超过 2 \cdot 10^5。
输出格式
对于每个测试用例,输出一个实数 —— 所需的最小时间。
样例输入
3
5
4 15 1 7 9
3
2 4 8
6
11 13 17 19 23 29
样例输出
11
2
12
样例说明
对于第一个测试用例,从数组 [4, 15, 1, 7, 19] 中删除的最佳索引是 k=2。数组变为 [4, 1, 7, 19],所需时间为 |4-1| + |1-7| + |7-19| = 3 + 6 + 12 = 21?等一下,这个计算似乎有问题。让我们重新检查一下:
删除 a_2=15 后,数组变为 [4, 1, 7, 9](注意原数组最后一个是 9,不是 19)。那么和为 |4-1| + |1-7| + |7-9| = 3 + 6 + 2 = 11,与输出 11 一致。
对于第二个测试用例,删除的最佳索引是 k=3。
AC 代码
// Problem: CF 2179 B
// Contest: Codeforces - Codeforces Round 1071 (Div. 3)
// URL: https://codeforces.com/contest/2179/problem/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);
void solve(){
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++){
cin>>a[i];
}
int tot=0;
for(int i=1;i<a.size();i++){
tot+=abs(a[i]-a[i-1]);
}
int ans=1e9;
for(int i=0;i<n;i++){
int cur=tot;
if(i==0){
cur-=abs(a[1]-a[0]);
}else if(i==n-1){
cur-=abs(a[n-1]-a[n-2]);
}else{
cur-=abs(a[i]-a[i-1]);
cur-=abs(a[i]-a[i+1]);
cur+=abs(a[i-1]-a[i+1]);
}
ans=min(ans,cur);
}
cout<<ans<<endl;
return ;
}
int main(){
ios;
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}