何老板有一个长度为 N N N的整数数列 A A A。
他让你任选一个整数 x x x,使得下面式子的值最小:
∣ A 1 − ( X + 1 ) ∣ + ∣ A 2 − ( X + 2 ) ∣ + ∣ A 3 − ( X + 3 ) ∣ + . . . . . . + ∣ A N − ( X + N ) ∣ |A_1-(X+1)|+|A_2-(X+2)|+|A_3-(X+3)|+......+|A_N-(X+N)| ∣A1−(X+1)∣+∣A2−(X+2)∣+∣A3−(X+3)∣+......+∣AN−(X+N)∣
请你计算出上面式子的最小值。
分析
这道题不算太难,但要提前知道一个知识点:
对于形如 ∣ a 1 − y ∣ + ∣ a 2 − y ∣ + . . . . . . + ∣ a n − y ∣ |a_1-y|+|a_2-y|+......+|a_n-y| ∣a1−y∣+∣a2−y∣+......+∣an−y∣式子,当其为最小值时, y y y当且仅当为序列 a a a的中位数
那我们只需要对上式拆开括号就可以变成这种形式: ∣ A i − ( X + i ) ∣ = ∣ ( A i − i ) − X ∣ |A_i-(X+i)|=|(A_i-i)-X| ∣Ai−(X+i)∣=∣(Ai−i)−X∣其中 A i − i A_i-i Ai−i是个定值,可以被提前求出;
现在就好办了,我们只需要把 A i A_i Ai预处理成 A i − i A_i-i Ai−i,然后求出新序列的中位数即是 X X X的值,最后带入求解即可;
时间复杂度 O ( N log N ) O(N\log N) O(NlogN),可以通过(求中位数时要排序!)
Code
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
int n,a[200005],ans,num;
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){scanf("%lld",&a[i]);a[i]-=i;}
sort(a+1,a+n+1);
if(n&1){num=a[n/2+1];}
else{num=(a[n/2]+a[n/2+1])/2;}
for(int i=1;i<=n;i++){ans+=abs(a[i]-num);}
printf("%lld",ans);
return 0;
}