NOIP2021 方差

$$
\begin{align}
n\overline{a}&=\sum_{i=1}^nai\
\
n^2D
&=n\sum
{i=1}^n(ai-\overline{a})^2\
&=n\sum
{i=1}^n ai^2-2n\overline{a}\sum{i=1}^n ai+n^2\overline{a}^2\
&=n\sum
{i=1}^n ai^2-2(\sum{i=1}^n ai)^2+(\sum{i=1}^n ai)^2\
&=n\sum
{i=1}^n ai^2-(\sum{i=1}^n a_i)^2\
\end{align
}
$$

观察题目中的式子,$a'i\leftarrow a{i-1}+a_{i+1}-a_i$,根据 CF1110E 的套路,可以差分,令 $di=a{i+1}-a_i(1\leq i\lt n)$,一次操作 $(2\leq i\lt n)$ 即:

$$
d'{i-1}=a'{i}-a'{i-1}=(a{i-1}+a_{i+1}-ai)-a{i-1}=a_{i+1}-a_i=d_i\
d'i=a'{i+1}-a'{i}=a{i+1}-(a{i-1}+a{i+1}-a_i)=ai-a{i-1}=d_{i-1}
$$

相当于交换 $d_{i-1},d_i(2\leq i\lt n)$,故 $d$ 可以通过若干次操作,变为任意 $d$ 的排列。

由于 $a1$ 不变,那么 $a$ 和 $d$ 是一一对应的。现在要求一个 $d$ 的排列使得 $n^2D$ 最小,继续推式子:
$$
\begin{align*}
n^2D
&=n\sum
{i=1}^n ai^2-(\sum{i=1}^n ai)^2\
&=n\sum
{i=1}^n ai^2-\sum{i=1}^n\sum_{j=1}^na_iaj\
&=\frac{1}{2}(n\sum
{i=1}^n ai^2-2\sum{i=1}^n\sum_{j=1}^na_iaj+n\sum{j=1}^n aj^2)\
&=\frac{1}{2}(\sum
{i=1}^n\sum_{j=1}^n(a_i-aj)^2)\
&=\sum
{i=1}^{n-1}\sum{j=i}^{n-1}(a{j+1}-ai)^2\
&=\sum
{i=1}^{n-1}\sum_{j=i}^{n-1}(di+d{i+1}+\cdots+d_j)^2\
\end{align*}
$$
$n^2D$ 取最小值时,$d$ 一定是先递减后递增的。

考虑在分界位置(即递减到递增)从小到大往两边加数,由于
$$
\begin{align}
n^2D
&=n\sum_{i=1}^n ai^2-(\sum{i=1}^n a_i)^2\
\end{align
}
$$
维护 $dp[k][s]$ 表示当前已经加入了 $k$ 个数,现在的 $a$ 之和为 $s$ 的最小 $\displaystyle \sum_{i=1}^n a_i^2$。

初始 $dp[1][s]=0$。

转移时考虑加到左边还是右边:

  • 左边:原来是 $a_1,a_2,\cdots,a_k$,现在变为 $d,a_1+d,a_2+d,\cdots,a_k+d$,新增的贡献为

$$
\begin{align}
\Delta
&=d^2+\sum_{i=1}^k (d+ai)^2-\sum{i=1}^k ai^2\
&=(k+1)d^2+2d\sum
{i=1}^ka_i\
&=(k+1)d^2+2ds\
\end{align
}
$$

  • 右边:原来是 $a_1,a_2,\cdots,a_k$,现在变为 $a_1,a_2,\cdots,a_k,a_k+d$,新增的贡献为
    $$
    \begin{align}
    \Delta
    &=(a_k+d)^2\
    \end{align
    }
    $$
    其实可以发现 $a_k$ 是固定的,为之前所有的 $d$ 之和,不需要再记录。

答案为 $\displaystyle \min_s{n\times dp[n][s]-s^2}$。

分析一下时间复杂度,第一维是 $O(n)$ 的,第二维是 $O(nV)$ 的,转移 $O(1)$。

但是可以发现 $d$ 为 $0$ 的转移可以忽略,第一维是 $O(\min(n,V))$ 的,总复杂度为 $O(nV^2)$,可以通过。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1ll<<60;
int n,a[11000],d[11000]; ll dp[510000];
ll sqr(ll x){ return x*x;}
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<n;i++) d[i]=a[i+1]-a[i];
    sort(d+1,d+n);

    for (int i=0;i<=500000;i++) dp[i]=INF;
    dp[0]=0; int lim=0,sum=0;
    for (int i=1;i<n;i++){
        if (!d[i]) continue;
        for (int s=lim;s>=0;s--){
            if (dp[s]==INF) continue;
            dp[s+sum+d[i]]=min(dp[s+sum+d[i]],dp[s]+sqr(sum+d[i]));
            dp[s+i*d[i]]=min(dp[s+i*d[i]],dp[s]+2*s*d[i]+i*sqr(d[i]));
            dp[s]=INF;
        }
        lim+=i*d[i]; sum+=d[i];
    }
    ll ans=INF;
    for (int i=0;i<=lim;i++)
        if (dp[i]!=INF) ans=min(ans,n*dp[i]-1ll*i*i);
    printf("%lld\n",ans);
    return 0;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇