P8920

『MdOI R5』Variance

题目描述

给定两个长度为 \(n\) 的整数序列 \(a,b\),满足:

  • \(\forall i\in [1,n),a_i\le a_{i+1},b_i\le b_{i+1}\)

  • \(\forall i\in [1,n],a_i\le b_i\)

有一个长度为 \(n\) 的实数序列 \(c\),满足 \(c_i\in [a_i,b_i]\),求 \(c\) 的方差的最大值。

你只需要输出答案乘上 \(n^2\) 之后的结果。容易证明这是一个整数。

提示

一个长度为 \(n\) 的序列 \(a\) 的方差为:\(\dfrac{1}{n}\sum\limits_{i=1}^n (a_i-\overline{a})^2\)。其中 \(\overline{a}=\dfrac{1}{n}\sum\limits_{i=1}^n a_i\)

本题的计算过程中可能会涉及到超过 long long 范围的数,此时可能需要用到 __int128 进行处理。

我们提供了以下代码,它可以用于输出一个 __int128 类型的数:

void print(__int128 x)
{
	if(x<0)
	{
		putchar('-');
		x=-x;
	}
	if(x<10)
	{
		putchar(x+48);
		return;
	}
	print(x/10);
	putchar(x%10+48);
}

输入格式

第一行,一个整数,表示 \(n\)

第二行,\(n\) 个整数,表示 \(a_1,a_2,\dots,a_n\)

第三行,\(n\) 个整数,表示 \(b_1,b_2,\dots,b_n\)

输出格式

共一行,一个整数,表示答案。

样例 #1

样例输入 #1

2
1 10
1 10

样例输出 #1

81

样例 #2

样例输入 #2

3
1 2 3
3 4 5

样例输出 #2

26

提示

对于 \(100\%\) 的数据,\(1\le n\le 10^6\)\(1\le a_i,b_i\le 10^9\)

\(\operatorname{Subtask} 1(10\%)\)\(n\le 2\times 10^3\)\(a_i=b_i\le 10^5\)

\(\operatorname{Subtask} 2(20\%)\)\(n\le 10\)\(a_i,b_i\le 5\)

\(\operatorname{Subtask} 3(20\%)\)\(n\le 2\times 10^3\)\(a_i,b_i\le 10^5\)

\(\operatorname{Subtask} 4(20\%)\)\(n\le 10^5\)\(a_i,b_i\le 2\times 10^3\)

\(\operatorname{Subtask} 5(30\%)\):无特殊限制。

样例说明 1

\(c\) 只可能为 \((1,10)\)

样例说明 2

一种最优的 \(c\)\((1,2,5)\)



Solution:
最开始的想法基本正确:
观察样例可以发现肯定是a[]取前面连续若干个 b[]取后面连续若干个(虽然最开始想的是b[]只取最后一个)
然后就可以枚举分界点i 用前缀和优化计算所求式子 更新答案即可

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int __int128
inline void read(int &n){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    n=x*f;
}
void print(__int128 x)
{
	if(x<0)
	{
		putchar('-');
		x=-x;
	}
	if(x<10)
	{
		putchar(x+48);
		return;
	}
	print(x/10);
	putchar(x%10+48);
}
__int128 n,a,b;
__int128 ans=0,s1[1000005],s2[1000005],s3[1000005],s4[1000005];
signed main()
{
	ios::sync_with_stdio(false);
	read(n);
	for(int i=1;i<=n;i++)read(a),s1[i]=s1[i-1]+a,s3[i]=s3[i-1]+a*a;
	for(int i=1;i<=n;i++)read(b),s2[i]=s2[i-1]+b,s4[i]=s4[i-1]+b*b;
	
	__int128 now_ans;
	for(int i=1;i<=n-1;i++)
	{
		now_ans=(n*(s3[i]+s4[n]-s4[i])-(s1[i]+s2[n]-s2[i])*(s1[i]+s2[n]-s2[i]));
		ans=max(ans,now_ans);
	}
	now_ans=(n*s3[n]-s1[n]*s1[n]);
	ans=max(ans,now_ans);
	now_ans=(n*s4[n]-s2[n]*s2[n]);
	ans=max(ans,now_ans);
	print(ans);
	return 0;
}
# 注意: 其实最开始有出错是因为a*a b*b超范围了 所以(ll)a*a (ll)b*b 就可以了
# 	**很多题猜到大概结论后就勇敢地写!!!**
posted @ 2023-01-01 23:36  PKU_IMCOMING  阅读(28)  评论(0)    收藏  举报