在遥远的北方有一个国家,这个国家有一个房地产商,他新盖的小区里有n座楼房他准备通过这个小区大赚一笔。
但是国王胖赤耳颁布了一条奇怪的法令:一个小区中任意两个房子的高度差必须要小于等于M米。因此房地产商必须要调整房子的高度,使得任意两个房子的高度差均小于等于M米。每个房子只能改变一次高度,将一个房子的高度改变k米的花费是k^2万元,求房地产商最低要花费多少万元。
输入描述
输入第一行包含两个整数n,m(n,m <= 2e5)
接下来一行包含n个整数,分别代表每一个房子的高度(1≤h≤2e5)。
输出描述
输出一行一个整数代表房地产商的最低花费。
n=4 m=23
40 21 44 46
2
数据范围 n,m=2e5 不能2重循环
完全平方公式展开 求前缀和+平方前缀和即可
注意n,m,p,q 用ll 否则乘积会爆int
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn=2e5+5;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll a[maxn],prea[maxn],prea2[maxn],sufa[maxn],sufa2[maxn];
int main()
{
ios::sync_with_stdio(false);
ll n,m;
ll ans=inf;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
prea[0]=0;
for(int i=1;i<=n;i++)
{
prea[i]=prea[i-1]+a[i];
}
prea2[0]=0;
for(int i=1;i<=n;i++)
{
prea2[i]=prea2[i-1]+a[i]*a[i];
}
sufa[n+1]=0;
for(int i=n;i>=1;i--)
{
sufa[i]=sufa[i+1]+a[i];
}
sufa2[n+1]=0;
for(int i=n;i>=1;i--)
{
sufa2[i]=sufa2[i+1]+a[i]*a[i];
}
for(ll i=a[1];i<=a[n];i++)
{
ll p=lower_bound(a+1,a+n+1,i)-a;//第一个大于等于
ll q=upper_bound(a+1,a+n+1,i+m)-a-1;//第一个大于 最后一个小于等于
// cout<<p<<" "<<q<<endl;
ll qian=(p-1)*i*i-2*i*prea[p-1]+prea2[p-1];
ll hou=(n-q)*(i+m)*(i+m)-2*(i+m)*sufa[q+1]+sufa2[q+1];
// cout<<qian<<" "<<hou<<endl;
ans=min(ans,qian+hou);
}
cout<<ans<<endl;
return 0;
}
超时写法 枚举
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn=2e5+5;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll a[maxn],prea[maxn],prea2[maxn],sufa[maxn],sufa2[maxn];
int main()
{
ios::sync_with_stdio(false);
ll n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+n+1);
ll minn=inf;
for(ll i=a[1];i<=a[n];i++)
{
ll ans=0;
for(int j=1;j<=n;j++)
{
if(a[j]<i)
ans+=(i-a[j])*(i-a[j]);
else if(a[j]>=i && a[j]<=i+m)
continue;
else
ans+=(a[j]-(i+m))*(a[j]-(i+m));
}
minn=min(ans,minn);
}
cout<<minn<<endl;
return 0;
}