Description
给你一个数列A,希望你找出一个数字B。使得下面这个式子的值最小
Abs(A1-(B+1))+Abs(A2-(B+2))+Abs(A3-(B+3))+..........+Abs(An-(B+n))
Format
Input
第一行给出输入n
第二行给出数列A,数字的值在[1,1e9]
N<=2e5
Output
如题
Samples
输入数据 1
5
2 2 3 5 5
输出数据 1
2
思路
前铺知识:初中数学:绝对式和的最小值
这道题目其实把前铺知识看懂后就很简单了。
Abs(A1-(B+1))+Abs(A2-(B+2))+Abs(A3-(B+3))+..........+Abs(An-(B+n))
=Abs((A1-1)-B)+Abs((A2-2)-B)+Abs((A3-3)-B)+..........+Abs((An-n)-B)
所以我们可以边输入a[i]边把a[i]-=i,然后题目要求的是最后式子结果,然后将a[]数组排序,那么根据前铺知识的公式:
判断n是否为偶数,是的话就可以将数按排列顺序分成相等的两部分,用前面数的和减去后面数的和,就是所求结果,否则将数按最中间的数为分界点,前面的数分为一部分,后面的数分为一部分,用前面数的后,减去后面数的后,就是所求结果。
总结起来就是3步:
step 1:边输入a[i]边将a[i]-=i
step 2:将a数组排序
step 3:判断n是否为偶数,是的话就可以将数按排列顺序分成相等的两部分,用前面数的和减去后面数的和,就是所求结果,否则将数按最中间的数为分界点,前面的数分为一部分,后面的数分为一部分,用前面数的后,减去后面数的后,就是所求结果。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,a[1000001],s_1,s_2;
signed main()
{
cin>>n;
for(int i = 1; i <= n; i++)
{
cin>>a[i];
a[i] -= i;
}
sort(a + 1,a + n + 1);
if(n % 2 == 0)
{
for(int i = 1; i <= n / 2; i++) s_1 += a[i];
for(int i = n / 2 + 1; i <= n; i++) s_2 += a[i];
cout<<abs(s_1 - s_2);
}
else
{
for(int i = 1; i <= n / 2; i++) s_1 += a[i];
for(int i = n / 2 + 2; i <= n; i++) s_2 += a[i];
cout<<abs(s_1 - s_2);
}
return 0;
}