NKOJ P5608 求和

10 篇文章 0 订阅
4 篇文章 0 订阅

何老板有一个长度为 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| a1y+a2y+......+any式子,当其为最小值时, 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)=(Aii)X其中 A i − i A_i-i Aii是个定值,可以被提前求出;

现在就好办了,我们只需要把 A i A_i Ai预处理成 A i − i A_i-i Aii,然后求出新序列的中位数即是 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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值