【Codeforces】1659C Line Empire 题解

题目大意

在一条坐标轴上有 n n n个点需要占领,每个节点在 x i x_i xi,初始节点在 0 0 0处,且基地也在 0 0 0
每次行动时,设当前基地在 p p p处,那么可以做以下行动:

  • 把基地移动到一个已经占领的点 x i x_i xi,耗费 a ∗ ∣ x i − p ∣ a * |x_i - p| axip
  • 占领一个没有被占领的节点,消耗 b ∗ ∣ x i − p ∣ b * |x_i - p| bxip

给定 a , b , x i ( 1 ≤ n ≤ 2 ∗ 1 0 5 , 1 ≤ a , b ≤ 1 0 5 ) a,b,x_i(1\le n \le 2*10^5, 1 \le a, b \le 10^5) a,b,xi(1n2105,1a,b105),求占领所有节点的耗费最小值。
题目链接

思路

我们来考虑占领的最终状况。

我们把基地定在了 x p x_p xp处,然后把所有点给占领了。
我们设 s u m 1 sum1 sum1是点的距离的前缀和。
那么占领 x p x_p xp之后的所有点的费用就是 ( s u m 1 [ n ] − s u m 1 [ i ] − ( n − i ) ∗ x [ i ] ) ∗ b (sum1[n] - sum1[i] - (n - i) * x[i]) * b (sum1[n]sum1[i](ni)x[i])b
那么前面的点呢?
我们发现,不管我们什么时候移动基地,移动基地的费用都是 a ∗ x p a * x_p axp
所以我们最有解法一定是占领一个点,那么就把基地移动过去。这样我们占领的费用就是 b ∗ x p b * x_p bxp

可以发现,指定最终基地的落脚点,可以 O ( 1 ) O(1) O(1)的算出费用,那么我们就不妨枚举基地的落脚点,然后更新答案。

代码

#include <cstdio>
#include <iostream>
using namespace std;

const int maxN = 2e5 + 7;
int T, n;
long long a, b, x[maxN], sum1[maxN];

int main()
{
    scanf("%d", &T);
    while(T--) {
        scanf("%d%lld%lld", &n, &a, &b);
        for(int i = 1; i <= n; ++i) {
            scanf("%lld", &x[i]);
            sum1[i] = sum1[i - 1] + x[i];
        }
        long long ans = 1LL << 62;
        for(int i = 0; i <= n; ++i) {
            long long forward = x[i] * b, after = (sum1[n] - sum1[i] - (n - i) * x[i]) * b;
            ans = min(ans, forward + after + a * x[i]);
        }
        printf("%lld\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值