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) kaiaiaib1+b2++bk)+b1b1+b2b2++bkbk

b 1 b_1 b1~ b k b_k bk的和 与 b 1 ∗ b 1 b_1*b_1 b1b1~ b k ∗ b k b_k*b_k bkbk的和 可以用前缀和来预处理

完成优化

注:记得开 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 比赛(二分)(贪心—前缀和)的主要内容,如果未能解决你的问题,请参考以下文章

2021.8.10提高B组模拟2T1 单峰(快速幂)

2021.8.10提高B组模拟2T1 单峰(快速幂)

2017.07.07NOIP提高组模拟赛B组

2021.8.10提高B组模拟2T2 祖孙询问(lca)(倍增)

2021.8.10提高B组模拟2T4 数字(dp)

2021.8.10提高B组模拟2T4 数字(dp)