Codeforces Round #688 (Div. 2) B. Suffix Operations(1400)
1400
1400
1400构造捋一下,
- 题意:
给你一个
n
n
n个整数的数列
a
a
a。你可以进行两种操作:
1
、
1、
1、后缀+
1
1
1
2
、
2、
2、后缀 -
1
1
1 你可以改变其中的任何
1
1
1个数为任何整数,也可以不变,然后进行上述操作。问最少需要操作几次,才能使所有数相同。 - 思路:
看到这种前后缀操作次数的题目,第一想法是差分。我们可以想到,如果要所有数相等,那么差分数组除了第一个位置之外,后面的所有位置都应该为
0
0
0。可以想到对后缀
a
[
i
]
a[i]
a[i]~
a
[
n
]
a[n]
a[n]进行操作的话,只会改变差分数组中
d
[
i
]
d[ i ]
d[i] 的值,对于
i
i
i前面和后面的位置都没有影响。那么我们操作的目的就是要让差分数组的除第一个位置之外的值,都为
0
0
0。如果题目中没有说可以改变一个数的值的话,那么答案
O
(
n
)
O(n)
O(n)跑一遍即可求出。但是题目中还有一个改变操作,于是我们想到,如果减小
a
[
i
]
a[i]
a[i]的值,那么
d
[
i
]
d[ i ]
d[i]减小,
d
[
i
+
1
]
d[i+1]
d[i+1]增大;如果增加
a
[
i
]
a[i]
a[i]的值,那么
d
[
i
]
d[i]
d[i]增大,
d
[
i
+
1
]
d[i+1]
d[i+1]减小。我们改变值的目的肯定是要减少操作次数,那么只要顺着枚举每个位置,然后看如果改变这个位置的值能减少多少次操作,最后取大即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5+10;
int a[N];
void cf(){
int n;
cin>>n;
int sum=0;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=2;i<=n;i++){
sum+=abs(a[i]-a[i-1]);
}
int res=0;
res=max(abs(a[2]-a[1]),abs(a[n-1]-a[n]));
for(int i=2;i<=n-1;i++){
if(a[i]-a[i-1]<0&&a[i+1]-a[i]<0||a[i]-a[i-1]>0&&a[i+1]-a[i]>0)continue;
else{
int x=min(abs(a[i]-a[i-1]),abs(a[i+1]-a[i]));
res=max(res,x*2);
}
}
cout<<sum-res<<endl;
}
signed main(){
int t=1;
cin>>t;
while(t--){
cf();
}
}
|