1 条题解

  • 0
    @ 2026-4-30 0:30:04

    更好的阅读体验

    思路

    每一个硬币最终都会走到 2×n2 \times n 的矩形里面,所以不妨将它们先到其到矩形中最近的节点。

    现在只需要在这个矩形中调整使每一个位置都有一个硬币。贪心的,我们希望让 xx 更小的填的位置尽量靠前。

    从前往后扫,记 a,ba,b 分别表示 y=1,y=2y = 1,y = 2 的多余的硬币。当 a>0,b<0a > 0,b < 0 时,需要将 aa 分一些给 bb;当 a<0,b>0a < 0,b > 0 时,需要将 bb 分一些给 aa。因为我们在此时需要将 a+b|a| + |b| 个硬币移动到经过该点,加上贡献即可。

    Code

    #include <bits/stdc++.h>
    #define re register
    #define fst first
    #define snd second
    #define int long long
    
    using namespace std;
    
    typedef pair<int,int> pii;
    const int N = 1e5 + 10;
    const int inf = (int)(1e18) + 10;
    int n,ans;
    int num[N][5];
    
    inline int read(){
        int r = 0,w = 1;
        char c = getchar();
        while (c < '0' || c > '9'){
            if (c == '-') w = -1;
            c = getchar();
        }
        while (c >= '0' && c <= '9'){
            r = (r << 3) + (r << 1) + (c ^ 48);
            c = getchar();
        }
        return r * w;
    }
    
    signed main(){
        n = read();
        for (re int i = 1,x,y;i <= 2 * n;i++){
            x = read(),y = read();
            if (x < 1){ ans += (1 - x); x = 1; }
            else if (x > n){ ans += (x - n); x = n; }
            if (y <= 1){ ans += (1 - y); y = 1; }
            else{ ans += (y - 2); y = 2; }
            num[x][y]++;
        }
        for (re int i = 1,a = 0,b = 0;i <= n;i++){
            a += (num[i][1] - 1),b += (num[i][2] - 1);
            while (a > 0 && b < 0) a--,b++,ans++;
            while (a < 0 && b > 0) a++,b--,ans++;
            ans += (abs(a) + abs(b));
        } printf("%lld",ans);
        return 0;
    }
    
    • 1

    信息

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