C - Linear Approximation
题目大意:长度为n的序列,找任意一个整数b,使abs(a[i]-(i+b))的和最小。
先将a[i]减去i,那么就是求a[i]-b的绝对值和最小.
转换模型我们可以把a[i]看成数轴上的点,那么就是要求数轴上一个点到其他点的距离最小。
曾经在蓝书上看过这个结论,b这个点就是中位数。
证明一波:
image.png
假设找的点是蓝色点,向左移动d个单位,则左边点到它的距离-d,右边+d,那么-4d+2d=-2d减少了2d.
可见只要蓝点左右两边点数不同就不是最优解,那么使左右两边点数相同的就是这些点坐标的中位数了。
以上证明摘自蓝书p6.
那么b为中位数,我们就可以求出答案了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 #define ll long long 8 #define out(a) printf("%lld ",a) 9 using namespace std; 10 int n; 11 int num; 12 ll ans; 13 int a[200050]; 14 int read() 15 { 16 int s=0,t=1; char c; 17 while (c<‘0‘||c>‘9‘){if (c==‘-‘) t=-1; c=getchar();} 18 while (c>=‘0‘&&c<=‘9‘){s=s*10+c-‘0‘; c=getchar();} 19 return s*t; 20 } 21 int main() 22 { 23 n=read(); 24 for (int i=1;i<=n;i++) 25 a[i]=read(),a[i]-=i; 26 sort(a+1,a+n+1); 27 if (n&1) num=a[n/2+1]; 28 else num=a[n/2]; 29 for (int i=1;i<=n;i++) 30 ans+=abs(a[i]-num); 31 out(ans); 32 return 0; 33 }
原文地址:https://www.cnblogs.com/Kaleidoscope233/p/9277287.html
时间: 2024-10-10 03:41:11