test20180922 世界第一的猛汉王
Posted autoint
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了test20180922 世界第一的猛汉王相关的知识,希望对你有一定的参考价值。
题意
分析
代码
#include <bits/stdc++.h>
using LL = long long;
const int MAXN = 1e5 + 5;
int n, m, D;
std::pair<LL, LL> p1[MAXN], p2[MAXN];
struct Event {
LL x, y; int val;
Event() = default;
Event(LL _x, LL _y, int _v): x(_x), y(_y), val(_v) {}
}; std::vector<Event> events; // 扫描线事件
std::vector<LL> xlist, sorted; // x离散化列表,y离散化列表
namespace BIT {
int sum[MAXN * 3];
void Init() {
memset(sum, 0, sizeof sum);
}
#define lowbit(x) ((x) & -(x))
void Add(int a, int x) {
for (int i = a; i <= (int)sorted.size(); i += lowbit(i))
sum[i] += x;
}
int Query(int a) {
int res = 0;
for (int i = a; i > 0; i -= lowbit(i))
res += sum[i];
return res;
}
}
LL minAns = 0, maxAns = 0, minus = 0; // 加、减的总和
int covered[MAXN];
int Y(LL y) {
return std::lower_bound(sorted.begin(), sorted.end(), y) - sorted.begin() + 1;
}
LL C2(LL x) {
return x * (x - 1) / 2;
}
void Solve() {
events.clear(); // p2中x起止&y&+-1
xlist.clear(); // p2中x起止, p1中x
sorted.clear(); // p2中y,p1中y起止
for (int i = 1; i <= m; ++i) {
events.emplace_back(p2[i].first - D, p2[i].second, 1);
events.emplace_back(p2[i].first + D + 1, p2[i].second, -1);
xlist.push_back(p2[i].first - D);
xlist.push_back(p2[i].first + D + 1);
sorted.push_back(p2[i].second);
}
for (int i = 1; i <= n; ++i) {
xlist.push_back(p1[i].first);
sorted.push_back(p1[i].second - D - 1);
sorted.push_back(p1[i].second + D);
}
std::sort(xlist.begin(), xlist.end());
xlist.erase(std::unique(xlist.begin(), xlist.end()), xlist.end());
std::sort(sorted.begin(), sorted.end());
sorted.erase(std::unique(sorted.begin(), sorted.end()), sorted.end());
std::sort(events.begin(), events.end(), [] (const Event &a, const Event &b) { return a.x < b.x; });
BIT::Init();
int j1 = 0, j2 = 1;
for (LL x: xlist) {
while (j1 < (int)events.size() && events[j1].x == x) { // 把离散化的纵坐标加进去
BIT::Add(Y(events[j1].y), events[j1].val);
++j1;
}
while (j2 <= n && p1[j2].first == x) {
covered[j2] = BIT::Query(Y(p1[j2].second + D)) - BIT::Query(Y(p1[j2].second - D - 1)); // 询问离散化的纵坐标的区间和
++j2;
}
}
std::sort(covered + 1, covered + n + 1);
for (int i = 1; i <= n; ++i) {
minAns += 1LL * (n - i) * covered[i]; // n-i个比它大
maxAns += 1LL * (n - i) * covered[n - i + 1]; // n-i个比它大
minus += C2(covered[i]); // 加到减的总和里面
}
}
int main() {
#ifndef LOCAL
freopen("mhw.in", "r", stdin);
freopen("mhw.out", "w", stdout);
#endif
scanf("%d%d%d", &n, &m, &D);
for (int i = 1; i <= n; ++i) {
static int x, y;
scanf("%d%d", &x, &y);
p1[i] = std::make_pair(x + y, x - y);
}
for (int i = 1; i <= m; ++i) {
static int x, y;
scanf("%d%d", &x, &y);
p2[i] = std::make_pair(x + y, x - y);
}
std::sort(p1 + 1, p1 + n + 1);
std::sort(p2 + 1, p2 + m + 1);
Solve();
std::swap(n, m);
std::swap(p1, p2);
Solve();
printf("%lld %lld
", minAns - minus, maxAns - minus);
return 0;
}
以上是关于test20180922 世界第一的猛汉王的主要内容,如果未能解决你的问题,请参考以下文章