2021.8.10提高B组模拟2T3 比赛(二分)(贪心—前缀和)
Posted SSL_LKJ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.8.10提高B组模拟2T3 比赛(二分)(贪心—前缀和)相关的知识,希望对你有一定的参考价值。
比赛
题目大意
输入样例
2
3 7
1 5
输出样例
20.0
题目数据
解题思路
首先答案肯定时两两匹配,结果再除以n
接下来就就是优化
我们可以先将 B 数组进行排序
对于每一个 a i a_i ai有一些操作
在排好序的 B 数组中找到一个位置 k,使左边的数字小于它,右边的数字大于它(二分)
然后左边算(a[] - b[])的平方,右边算(b[] - a[])的平方
显然如果暴力做,还是会TLE
那我们就可以用 完全平方公式
那左边就成了
k ∗ a i ∗ a i − a i ∗ ( b 1 + b 2 + … … + b k ) + ( b 1 ∗ b 1 + b 2 ∗ b 2 + … … + b k ∗ b k ) k*a_i*a_i-a_i*(b_1 + b_2 + …… +b_k)+(b_1*b_1 + b_2*b_2 + …… +b_k*b_k) k∗ai∗ai−ai∗(b1+b2+……+bk)+(b1∗b1+b2∗b2+……+bk∗bk)
b 1 b_1 b1~ b k b_k bk的和 与 b 1 ∗ b 1 b_1*b_1 b1∗b1~ b k ∗ b k b_k*b_k bk∗bk的和 可以用前缀和来预处理
就完成优化了
注:记得开 long long 和 特判
AC代码
#include<algorithm>
#include<cstdio>
using namespace std;
long long n,a[50005],b[50005],f[50005],fa[50005];
double ans;
void work(long long x)//二分
long long l=1,r=n,k=0;
if(a[x]>=b[n])//特判
ans+=n*a[x]*a[x]-2ll*a[x]*f[n]+fa[n];
return;
if(a[x]<=b[1])
ans-=n*a[x]*a[x]-2ll*a[x]*f[n]+fa[n];
return;
while(l<=r)
long long mid=(l+r)/2ll;
if(a[x]>=b[mid])l=mid+1,k=mid;
else r=mid-1;
ans+=k*a[x]*a[x]-2ll*a[x]*f[k]+fa[k]-((n-k)*a[x]*a[x]-2ll*a[x]*(f[n]-f[k])+(fa[n]-fa[k]));
int main()
scanf("%lld",&n);
for(long long i=1;i<=n;i++)scanf("%lld",&a[i]);
for(long long i=1;i<=n;i++)scanf("%lld",&b[i]);
sort(b+1,b+n+1);
for(long long i=1;i<=n;i++)//预处理
f[i]=f[i-1]+b[i];
fa[i]=fa[i-1]+b[i]*b[i];
for(long long i=1;i<=n;i++)work(i);
printf("%.1lf",ans/(n*1.0));
return 0;
谢谢
以上是关于2021.8.10提高B组模拟2T3 比赛(二分)(贪心—前缀和)的主要内容,如果未能解决你的问题,请参考以下文章