1 条题解
-
0
自动搬运
来自洛谷,原作者为

jiangly
这个家伙很菜,什么也没有留下搬运于
2025-08-24 22:24:17,当前版本为作者最后更新于2020-09-19 12:22:19,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
首先可以扫描线 + 线段树求出每个询问四个方向的第一个点,通过这些点把询问拆成四个方向的凸包。
预处理每对点逆时针沿凸包走的叉积和 (如左下到右上就是沿右下凸包走)。每个询问将四个方向求和再除以 即可。
时间复杂度 。
#include <bits/stdc++.h> constexpr int N = 3e3, M = 1e6, S = 1 << 21; int n, m, k; struct Point { int x, y; Point(int x = 0, int y = 0) : x(x), y(y) {} } p[N]; bool operator<(const Point &lhs, const Point &rhs) { return lhs.x != rhs.x ? lhs.x < rhs.x : lhs.y < rhs.y; } int64_t cross(const Point &lhs, const Point &rhs) { return 1ll * lhs.x * rhs.y - 1ll * lhs.y * rhs.x; } Point operator-(const Point &lhs, const Point &rhs) { return Point(lhs.x - rhs.x, lhs.y - rhs.y); } int a[N]; int64_t f[N][N]; int xl[M], xr[M], yl[M], yr[M]; int b[M]; int pt[M][4]; int lg; int arr[S]; void modify(int x, int v) { for (x += (1 << lg) + 1; x; x /= 2) arr[x] = std::min(arr[x], v); } int rangeMin(int l, int r) { int res = n; for (l += (1 << lg), r += (1 << lg) + 2; l ^ r ^ 1; l /= 2, r /= 2) { if (l % 2 == 0) res = std::min(res, arr[l ^ 1]); if (r % 2 == 1) res = std::min(res, arr[r ^ 1]); } return res; } void work(int id, int offset = 0) { std::iota(a, a + n, 0); std::sort(a, a + n, [&](int i, int j) { return p[i] < p[j]; }); std::iota(b, b + m, 0); std::sort(b, b + m, [&](int i, int j) { return xl[i] > xl[j]; }); std::fill(arr, arr + (1 << (lg + 1)), n); for (int i = n - 1, qi = 0; i >= 0; --i) { int u = a[i]; int w = u; for (int j = i + 1; j < n; ++j) { int v = a[j]; if (p[v].y < p[u].y) continue; if (cross(p[w] - p[u], p[v] - p[u]) <= 0) w = v; f[u][v] = cross(p[u], p[w]) + f[w][v]; } modify(p[u].y + offset, i); int lim = i == 0 ? -k - 1 : p[a[i - 1]].x; while (qi < m && xl[b[qi]] > lim) { int j = b[qi]; pt[j][id] = a[rangeMin(yl[j] + offset, yr[j] + offset)]; ++qi; } } } void rotate() { for (int i = 0; i < n; ++i) { std::swap(p[i].x, p[i].y); p[i].x = -p[i].x; } for (int i = 0; i < m; ++i) { std::swap(xl[i], yl[i]); std::swap(xr[i], yr[i]); std::swap(xl[i], xr[i]); xl[i] = -xl[i]; xr[i] = -xr[i]; } } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cin >> k >> n; while ((1 << lg) < k + 3) ++lg; for (int i = 0; i < n; ++i) std::cin >> p[i].x >> p[i].y; std::cin >> m; for (int i = 0; i < m; ++i) std::cin >> xl[i] >> xr[i] >> yl[i] >> yr[i]; work(0); rotate(); work(3); rotate(); work(2, k); rotate(); work(1, k); for (int i = 0; i < m; ++i) { int64_t area = 0; for (int j = 0; j < 4; ++j) area += f[pt[i][j]][pt[i][(j + 1) % 4]]; std::cout << area / 2 << "." << "05"[area % 2] << "\n"; } return 0; }
- 1
信息
- ID
- 5880
- 时间
- 5000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者