提交记录:点这里
我的想法是:
先求出所有点相互加起来的曼哈顿距离
然后考虑夹在两条相邻x方向或两条相邻y方向的所有点带来的额外贡献
求大佬帮忙看看QWQ
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
char c = getchar();
x = 0;
int f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -f;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = (x << 1) + (x << 3) + c - '0';
c = getchar();
}
x = f * x;
}
int n, m, k;
const int maxn = 1e5 + 5;
const int maxk = 2e5 + 5;
const int base = 1e5 + 1;
typedef long long ll;
int a[maxn], b[maxn];
struct node {
int x, y;
node(int _X = 0, int _y = 0) : x(_X), y(_y) {}
void In() {
read(x);
read(y);
x += base;
y += base;
}
} poi[maxk];
ll ans1, ans2, ans3, ans4;
bool cmp_x(node e1, node e2) {
return e1.x < e2.x;
}
bool cmp_y(node e1, node e2) {
return e1.y < e2.y;
}
multiset<int> st;
multiset<int>::iterator it;
int main() {
read(n);
read(m);
read(k);
a[0] = -(base << 4);
a[n + 1] = base << 4;
b[0] = -(base << 4);
b[m + 1] = base << 4;
for(int i = 1; i <= n; i ++) {
read(a[i]);
a[i] += base;
}
for(int i = 1; i <= m; i ++) {
read(b[i]);
b[i] += base;
}
sort(a + 1, a + n + 1);
sort(b + 1, b + m + 1);
for(int i = 1; i <= k; i ++) poi[i].In();
// 1. get_x
ll sum = 0;
sort(poi + 1, poi + k + 1, cmp_x);
for(int i = 1; i <= k; i ++) {
ans1 += (ll)poi[i].x * (i - 1) - sum;
sum += poi[i].x;
}
// 2. get_between_heng_and_heng_is_shu
int l = 1, r;
for(int i = 1; i <= n + 1; i ++) {
while(poi[l].x <= a[i - 1]) l ++;
if(l > k) break;
r = l - 1;
while(r < k && poi[r + 1].x < a[i]) r ++;
if(r == l - 1) continue;
for(int j = l, tmp; j <= r; j ++) {
tmp = min(poi[j].x - a[i - 1], a[i] - poi[j].x);
st.insert(tmp);
}
for(int j = l, u; j <= r; j ++) {
it = st.begin();
u = *it;
ans2 += ((ll)r - j) * (u << 1);
st.erase(it);
}
}
// 3. get_y
sum = 0;
sort(poi + 1, poi + k + 1, cmp_y);
for(int i = 1; i <= k; i ++) {
ans3 += (ll)poi[i].y * (i - 1) - sum;
sum += poi[i].y;
}
// 4. get_between_shu_and_shu_is_heng
l = 1;
for(int i = 1; i <= m + 1; i ++) {
while(poi[l].y <= b[i - 1]) l ++;
if(l > k) break;
r = l - 1;
while(r < k && poi[r + 1].y < b[i]) r ++;
if(r == l - 1) continue;
for(int j = l, tmp; j <= r; j ++) {
tmp = min(poi[j].y - b[i - 1], b[i] - poi[j].y);
st.insert(tmp);
}
for(int j = l, u; j <= r; j ++) {
it = st.begin();
u = *it;
ans4 += ((ll)r - j) * (u << 1);
st.erase(it);
}
}
// 5. output
ll ans = ans1 + ans2 + ans3 + ans4;
printf("%lld\n", ans);
return 0;
}