选址


<mstyle mathcolor="red"> </mstyle> \color{red}{正解部分}

考虑什么时候 i i i 会对 x x x 产生贡献,
c i x i 2 &gt; 0 c_i-|x-i|^2 &gt; 0 cixi2>0 时, 会产生贡献, 解方程得到 x ( i c i , i + c i ) x∈(i-\sqrt{c_i}, i+\sqrt{c_i}) x(ici ,i+ci ) .

\therefore x ( i c i , i + c i ) x∈(i-\sqrt{c_i}, i+\sqrt{c_i}) x(ici ,i+ci ) 时, i i i 会对 x x x 产生贡献 .

贡献为 c i i 2 + 2 i x x 2 c_i-i^2 + 2ix - x^2 cii2+2ixx2,

  • c i i 2 c_i-i^2 cii2 为常数, 可以直接使用一个差分数组处理 .
  • 2 i x 2i*x 2ix 的系数 2 i 2i 2i 使用一个差分数组处理 .
  • 1 x 2 1*x^2 1x2 的系数 1 1 1 使用一个差分数组处理 .

<mstyle mathcolor="red"> </mstyle> \color{red}{实现部分}

#include<bits/stdc++.h>
#define reg register
typedef long long ll;

const int maxn = 100005;

int N;

ll C[maxn];
ll cf1[maxn];
ll cf2[maxn];
ll cf3[maxn];

int main(){
        scanf("%d", &N);
        for(reg int i = 1; i <= N; i ++) scanf("%lld", &C[i]);
        for(reg int i = 1; i <= N; i ++){
                int l = std::max(1, (int)(i*1.0-sqrt(C[i])+1.0));
                int r = std::min(N, (int)(i*1.0+sqrt(C[i])));
                cf1[l] += C[i] - 1ll*i*i,
                cf1[r+1] -= C[i] - 1ll*i*i;
                cf2[l] += 2ll*i, cf2[r+1] -= 2ll*i;
                cf3[l] ++, cf3[r+1] --;
        }
        ll a = 0, b = 0, c = 0;
        for(reg int i = 1; i <= N; i ++){
                a += cf1[i], b += cf2[i], c += cf3[i];
                printf("%lld ", a + b*i - c*i*i);
        }
        return 0;
}