test20180922 世界第一的猛漢王
阿新 • • 發佈:2018-12-12
題意
分析
程式碼
#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\n", minAns - minus, maxAns - minus); return 0; }