选址 [差分]

选址


color{red}{正解部分}

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

hereforex(ici,i+ci)x∈(i-sqrt{c_i}, i+sqrt{c_i}) 时, ii 会对 xx 产生贡献 .

贡献为 cii2+2ixx2c_i-i^2 + 2ix - x^2,

  • cii2c_i-i^2 为常数, 可以直接使用一个差分数组处理 .
  • 2ix2i*x 的系数 2i2i 使用一个差分数组处理 .
  • 1x21*x^2 的系数 11 使用一个差分数组处理 .

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;
}
原文地址:https://www.cnblogs.com/zbr162/p/11822517.html