世界第一的猛汉王

题目链接

在同种中统计贡献,发现是减交集取最值。曼哈顿转切比雪夫,然后二维数点。注意要提前减去交的贡献(利用异色统计贡献),转化为可以批量计算贡献的东西。

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;
}
posted @ 2020-09-08 12:52  JiaZP  阅读(252)  评论(0编辑  收藏  举报