1 条题解

  • 0
    @ 2025-7-13 15:52:34

    O(M)O(M) 贪心

    下面所用字母为题面中代表含义。

    车提供的贡献为:ap2+b(xp)2a * p * 2 + b * (x - p) * 2

    简单分析这个式子

    1. a=ba=b 时,pp 对贡献无影响
    2. a>ba>b 时,随着 pp 的增大贡献单调增加。
    3. a<ba<b 时,随着 pp 的增大贡献单调减少。

    因为单调性所以车应该尽可能的靠近两个端点。

    结论1: 车辆的起始位置在两端

    pp 是到A市(0点)的距离,这意味着如果某辆车去A市次数更多,那么这辆车在货车的相对顺序中应该更靠前。

    结论2: 车的相对顺序为:由 aba-b 的值从大到小排列。

    综合两个结论,枚举车可能停靠的所有位置,求出最小值答案。

    
    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    typedef pair<LL, LL> PII;
    
    #define x first
    #define y second
    
    const int N = 2e5 + 10, M = 60;
    
    int n, m, x;
    PII site[N], car[N];
    
    bool cmp(PII a, PII b)
    {
        return a.x - a.y > b.x - b.y;
    }
    
    LL cal(int i, int j) // 位置下标,车下标。计算对答案的贡献
    {
        return car[j].x * site[i].x * 2 + car[j].y * (x - site[i].x) * 2;
    }
    
    int main()
    {
        cin >> n >> m >> x;
        for(int i = 1; i <= n; i ++) cin >> site[i].x >> site[i].y;
        for(int i = 1; i <= m; i ++) cin >> car[i].x >> car[i].y;
        
        sort(site + 1, site + 1 + n);
        sort(car + 1, car + 1 + m, cmp);
        
        LL ans = 0;
        vector<int> v(m + 1); // 保存每个车的位置
        for(int i = 1, j = 1; i <= n && j <= m; i ++) //计算所有车全放前面的结果
        {
            for(int k = 0; k < site[i].y; k ++)
            {
                ans += cal(i, j);
                v[j] = i;
                j ++;
                if(j > m) break;
            }
        }
        
        LL t = ans; 
        for(int i = n, j = m; i >= 1 && j >= 1; i --) // 枚举所有车辆放置情况
        {
            for(int k = 0; k < site[i].y; k ++)
            {
                t = t - cal(v[j], j) + cal(i, j);
                ans = min(ans, t);
                j --;
                if(j < 1) break;
            }
        }
        cout << ans << endl;
    }
    
    
    • 1

    信息

    ID
    188
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    17
    已通过
    2
    上传者