世界第一的猛汉王
在同种中统计贡献,发现是减交集取最值。曼哈顿转切比雪夫,然后二维数点。注意要提前减去交的贡献(利用异色统计贡献),转化为可以批量计算贡献的东西。
inline void clear() {
memset(ls, 0, sizeof(ls));
memset(rs, 0, sizeof(rs));
memset(sum, 0, sizeof(sum));
memset(rt, 0, sizeof(rt));
ttot = 0;
}
int cnt[N];
inline int Query(ll xl, ll xr, ll yl, ll yr) {
if (xl > xr || yl > yr) return 0;
int tl = max(yl, 1ll), tr = min(yr, (ll)Up);
int kl = max(xl, 1ll), kr = min(xr, (ll)Up);
xl = lower_bound(bz + 1, bz + 1 + m, (zuob){kl, 0}) - bz;
xr = lower_bound(bz + 1, bz + 1 + m, (zuob){kr + 1, 0}) - bz - 1;
if (xl > xr) return 0;
int res = query(1, Up, tl, tr, rt[xl - 1], rt[xr]);
return res;
}
inline void work1() {
for (register int i = 1; i <= m; ++i) add(1, Up, bz[i].y, rt[i - 1], rt[i]);
for (register int i = 1; i <= n; ++i) {
cnt[i] = Query(1ll * zb[i].x - d, 1ll * zb[i].x + d, 1ll * zb[i].y - d, 1ll * zb[i].y + d);
}
}
int cnt_[N];
inline int Query_(ll xl, ll xr, ll yl, ll yr) {
if (xl > xr || yl > yr) return 0;
int tl = max(yl, 1ll), tr = min(yr, (ll)Up);
int kl = max(xl, 1ll), kr = min(xr, (ll)Up);
xl = lower_bound(zb + 1, zb + 1 + n, (zuob){kl, 0}) - zb;
xr = lower_bound(zb + 1, zb + 1 + n, (zuob){kr + 1, 0}) - zb - 1;
if (xl > xr) return 0;
return query(1, Up, tl, tr, rt[xl - 1], rt[xr]);
}
inline void work2() {
for (register int i = 1; i <= n; ++i) add(1, Up, zb[i].y, rt[i - 1], rt[i]);
for (register int i = 1; i <= m; ++i) {
cnt_[i] = Query_(1ll * bz[i].x - d, 1ll * bz[i].x + d, 1ll * bz[i].y - d, 1ll * bz[i].y + d);
}
}
signed main() {
read(n), read(m), read(d);
for (register int i= 1; i <= n; ++i) zb[i].Read();
for (register int i = 1; i <= m; ++i) bz[i].Read();
sort(zb + 1, zb + 1 + n); sort(bz + 1, bz + 1 + m);
work1();
clear();
work2();
sort(cnt + 1, cnt + 1 + n);
sort(cnt_ + 1, cnt_ + 1 + m);
for (register int i = 1; i <= n; ++i) {
long long tmp = cnt[i];
Mx -= tmp * (tmp - 1) / 2;
Mn -= tmp * (tmp - 1) / 2;
Mx += tmp * (i - 1);
Mn += tmp * (n - i);
}
for (register int i = 1; i <= m; ++i) {
int tmp = cnt_[i];
Mx -= 1ll * tmp * (tmp - 1) / 2;
Mn -= 1ll * tmp * (tmp - 1) / 2;
Mx += 1ll * tmp * (i - 1);
Mn += 1ll * tmp * (m - i);
}
printf("%lld %lld\n", Mn, Mx);
return 0;
}