1 条题解

  • 3
    @ 2024-6-28 21:18:15
    • 由于向上运动不花费体力,会合点的 yy 坐标可以无限大,因此只需要考虑会合点的 xx 坐标即可。
    • 不难发现,每只蜘蛛最优移动路径只有两种:
      • 在当前 yy 坐标上改变 xx 坐标(设改变量为 Δx\Delta x),然后向上运动,花费 ry0Δxry_0\Delta x 点体力(其中 y0y_0 是初始的 yy 坐标)。
      • 向下运动到中心点 OO,然后向上运动,花费 dy0dy_0 点体力。
    • 由上可知,我们只需要关注 Δx\Delta xl=drl=\dfrac{d}{r} 的大小关系,即可确定每只蜘蛛的最优移动路径。
    • 因此,我们枚举会合点的 xx 坐标,然后差分(结合斜率)维护花费的总体力即可。
    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N = 1e5 + 12;
    int K[N], D[N], R[N], A[N];
    int move(int f, int s, int n)
    {
        return (f + s + n) % n;
    }
    int dis(int f, int t, int n)
    {
        int ans = abs(t - f);
        return min(ans, n - ans);
    }
    void build(int n, int d, int r, int l)
    {
        for (int i = 0; i <= n - 1; i++)
        {
            if (l >= n / 2 && n % 2 == 1)
            {
                // i = 1, n = 7
                // pos: 0 1 2 3 4 5 6
                // dis: 1 0 1 2 3 3 2
                K[move(i, n / 2 + 1, n)] += -1 * A[i];
                K[move(i, n / 2 + 2, n)] += -1 * A[i];
                K[move(i, 1, n)] += 2 * A[i];
            }
    
            if (l >= n / 2 && n % 2 == 0)
            {
                // i = 1, n = 6
                // pos: 0 1 2 3 4 5
                // dis: 1 0 1 2 3 2
                K[move(i, n / 2 + 1, n)] += -2 * A[i];
                K[move(i, 1, n)] += 2 * A[i];
            }
            if (l < n / 2)
            {
                // i = 1, n = 8, l = 2
                // pos: 0 1 2 3 4 5 6 7
                // dis: 1 0 1 2 d d d 2
                R[move(i, l + 1, n)] += -l * A[i];
                K[move(i, l + 1, n)] += -1 * A[i];
                D[move(i, l + 1, n)] += 1 * A[i];
                R[move(i, -l, n)] += l * A[i] + A[i];
                K[move(i, -l, n)] += -1 * A[i];
                D[move(i, -l, n)] += -1 * A[i];
                K[move(i, 1, n)] += 2 * A[i];
            }
        }
    }
    signed main()
    {
        freopen("spider.in", "r", stdin);
        freopen("spider.out", "w", stdout);
        int m, n, d, r;
        cin >> m >> n >> d >> r;
        for (int i = 1; i <= m; i++)
        {
            int x, y;
            cin >> x >> y;
            A[x] += y;
        }
        int l = d / r;
        long long a0 = 0, d0 = 0, r0 = 0;
        for (int i = 0; i <= n - 1; i++)
        {
            if (dis(0, i, n) <= l) a0 += dis(0, i, n) * r * A[i], r0 += dis(0, i, n) * A[i];
            else a0 += d * A[i], d0 += A[i];
        }
        long long a1 = 0, d1 = 0, r1 = 0;
        for (int i = 0; i <= n - 1; i++)
        {
            if (dis(1, i, n) <= l) a1 += dis(1, i, n) * r * A[i], r1 += dis(1, i, n) * A[i];
            else a1 += d * A[i], d1 += A[i];
        }
        build(n, d, r, l);
        long long kk = r1 - r0 - R[1], dd = d1, rr = r1, aa = a1, ans = min(a0, a1);
        for (int i = 2; i <= n - 1; i++)
        {
            kk += K[i], dd += D[i], rr += R[i];
            rr += kk;
            aa = rr * r + dd * d;
            ans = min(ans, aa);
        }
        cout << ans << endl;
        return 0;
    }
    
    • 1

    信息

    ID
    4
    时间
    1000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    30
    已通过
    5
    上传者