1 条题解

  • 0
    @ 2025-12-1 18:56:05

    题解

    di=AiBid_i=A_i-B_i,正数表示多余的土,负数表示缺土。把所有正值按下标记录为供给点,负值为需求点。运输单位成本为 zcdotijz\\cdot|i-j|,但你也可以选择“挖掉再买”的替代方案,成本恒为 x+yx+y,因此实际在两点间搬运一单位的最优成本为

    $$\\operatorname{cost}(i,j)=\\min\\bigl(z\\cdot|i-j|,\,x+y\\bigr). $$

    多余/缺少的总量不一定相等:若 sumdi>0\\sum d_i>0,剩余的土只能挖掉,花费 yy;若 sumdi<0\\sum d_i<0,缺的土只能购买,花费 xx。先把这一部分加入答案,其余部分则在供给点与需求点之间配对搬运。

    由于搬运成本关于下标的绝对值函数满足一维最优匹配的单调性,按下标从左到右贪心配对即可得到最小费用:用两个指针遍历供给列表和需求列表,每次输送 flow=min(surplus, deficit),累加 flow * min(z * distance, x + y),消耗掉一方就移动相应指针。

    复杂度

    • 时间:mathcalO(N)\\mathcal{O}(N),每个位置至多入队出队一次。
    • 空间:mathcalO(N)\\mathcal{O}(N)

    参考实现

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int N;
        long long x, y, z;
        if (!(cin >> N >> x >> y >> z)) return 0;
        vector<long long> A(N + 1), B(N + 1);
        for (int i = 1; i <= N; ++i) cin >> A[i] >> B[i];
    
        struct Node { int pos; long long amt; };
        vector<Node> sur, def;
        long long sumSur = 0, sumDef = 0;
        for (int i = 1; i <= N; ++i) {
            long long d = A[i] - B[i];
            if (d > 0) { sur.push_back({i, d}); sumSur += d; }
            else if (d < 0) { def.push_back({i, -d}); sumDef += -d; }
        }
    
        long long ans = 0;
        if (sumSur > sumDef) ans += (sumSur - sumDef) * y; // 多余的挖掉
        else ans += (sumDef - sumSur) * x;                  // 不足的买土
    
        size_t i = 0, j = 0;
        while (i < sur.size() && j < def.size()) {
            long long flow = min(sur[i].amt, def[j].amt);
            long long dist = llabs((long long)sur[i].pos - def[j].pos);
            long long costPer = min(z * dist, x + y);
            ans += flow * costPer;
            sur[i].amt -= flow;
            def[j].amt -= flow;
            if (sur[i].amt == 0) ++i;
            if (def[j].amt == 0) ++j;
        }
    
        cout << ans << '\n';
        return 0;
    }
    • 1

    信息

    ID
    5722
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    4
    已通过
    1
    上传者