选址 [差分]

选 址 选址


正 解 部 分 \color{red}{正解部分}

考虑什么时候 i i i 会对 x x x 产生贡献,
c i − ∣ x − i ∣ 2 > 0 c_i-|x-i|^2 > 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 使用一个差分数组处理 .

实 现 部 分 \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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值