思路
每一个硬币最终都会走到 \(2 \times n\) 的矩形里面,所以不妨将它们先到其到矩形中最近的节点。
现在只需要在这个矩形中调整使每一个位置都有一个硬币。贪心的,我们希望让 \(x\) 更小的填的位置尽量靠前。
从前往后扫,记 \(a,b\) 分别表示 \(y = 1,y = 2\) 的多余的硬币。当 \(a > 0,b < 0\) 时,需要将 \(a\) 分一些给 \(b\);当 \(a < 0,b > 0\) 时,需要将 \(b\) 分一些给 \(a\)。因为我们在此时需要将 \(|a| + |b|\) 个硬币移动到经过该点,加上贡献即可。
Code
#include <bits/stdc++.h>
#define re register
#define fst first
#define snd second
#define int long longusing 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;
}