选址 [差分]

选址


<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;
}
全部评论

相关推荐

27届毕业,最近想找一段大厂实习,感觉简历有些问题,好多都不给面,求大佬们指点,最近好焦虑
重生之我学Java干...:我从后端的角度分析一下你的第一个项目,我感觉亮点不是很突出。因为我是因为组内有需求,临时上手学react干活。我用到的技术基本就cover你那个智慧园区管理平台的很多亮点了。那作为比较专业的前端,你上述的内容是不是有点单薄呢。感觉还得包装
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务