# 题解 P3964 【[TJOI2013]松鼠聚会】

## Description

$(0 \leq n \leq 10^5,-10^9 \leq x_i,y_i \leq 10^9)$

## Code

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

template <class T>
x = 0;
char c = getchar();
bool f = 0;
for (; !isdigit(c); c = getchar()) f ^= c == '-';
for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
x = f ? -x : x;
}

template <class T>
inline void write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
T y = 1;
int len = 1;
for (; y <= x / 10; y *= 10) ++len;
for (; len; --len, x %= y, y /= 10) putchar(x / y + 48);
}

const int MAXN = 1e5;
int n, x[MAXN + 5], y[MAXN + 5], p[MAXN + 5], q[MAXN + 5];
LL ans = 0x7fffffffffffffff, prex[MAXN + 5], prey[MAXN + 5];

int main() {
for (int a, b, i = 1; i <= n; ++i) {
x[i] = p[i] = a + b, y[i] = q[i] = a - b;//转曼哈顿距离，且乘上 2
}
sort(p + 1, p + n + 1), sort(q + 1, q + n + 1);//排序
for (int a, b, i = 1; i <= n; ++i)//维护前缀和
prex[i] = prex[i - 1] + p[i], prey[i] = prey[i - 1] + q[i];
for (int posx, posy, i = 1; i <= n; ++i) {
posx = lower_bound(p + 1, p + n + 1, x[i]) - p;
posy = lower_bound(q + 1, q + n + 1, y[i]) - q;
//二分找到 x[i] 和 y[i] 是所有点中第几个大的
LL sumx, sumy;
sumx = (LL) posx * x[i] - prex[posx] +
prex[n] - prex[posx] - (LL) (n - posx) * x[i];//计算横坐标贡献
sumy = (LL) posy * y[i] - prey[posy] +
prey[n] - prey[posy] - (LL) (n - posy) * y[i];//计算纵坐标贡献
ans = min(ans, sumx + sumy);
}
write(ans / 2);//答案不要忘记除回去
putchar('\n');
return 0;
}

2019-06-10 21:51:26 in 题解