【题目链接】
【思路要点】
- 枚举发射源,将发射源当做原点,对敌人和激光塔极角排序。
- 由于敌人纵坐标均为正,而其它点均为负,因此每两个角度差在\(\pi\)以内的激光塔内部的敌人的个数之和就是该发射源对答案的贡献。
- 用前缀和以及Two Pointers可以在\(O(N)\)的时间内统计一个发射源的贡献。
- 时间复杂度\(O(N^2LogN)\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 2005; const double pi = acos(-1); template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct point {int x, y; }; point operator + (point a, point b) {return (point) {a.x + b.x, a.y + b.y}; } point operator - (point a, point b) {return (point) {a.x - b.x, a.y - b.y}; } long long operator * (point a, point b) {return 1ll * a.x * b.y + 1ll * a.y * b.x; } struct info {point pos; double alpha; bool type; }; info a[MAXN]; point p[MAXN]; int n, m, pre[MAXN]; double PolarAngle(point a) {return atan2(a.y, a.x); } bool cmp(info a, info b) {return a.alpha < b.alpha; } int main() { read(n); for (int i = 1; i <= n; i++) { read(a[i].pos.x), read(a[i].pos.y); a[i].type = true; } read(m); for (int i = 1; i <= m; i++) read(p[i].x), read(p[i].y); int k; read(k); n += k; for (int i = n - k + 1; i <= n; i++) { read(a[i].pos.x), read(a[i].pos.y); a[i].type = false; } long long ans = 0; for (int j = 1; j <= m; j++) { for (int i = 1; i <= n; i++) a[i].alpha = PolarAngle(a[i].pos - p[j]); sort(a + 1, a + n + 1, cmp); for (int i = 1; i <= n; i++) pre[i] = pre[i - 1] + a[i].type; long long sum = pre[1] * (!a[1].type), cnt = !a[1].type; for (int i = 1, j = 1; i <= n; i++) { if (j == i - 1) { j = i; if (!a[i].type) { cnt++; sum += pre[i]; } } int k = j % n + 1; while (k != i && (k > i && a[k].alpha - a[i].alpha < pi || k < i && a[k].alpha - a[i].alpha + 2 * pi < pi)) { j = k; if (!a[k].type) { cnt++; sum += pre[k]; if (k < i) sum += pre[n]; } k = j % n + 1; } if (!a[i].type) { ans += sum - cnt * pre[i]; cnt--; sum -= pre[i]; } } } writeln(ans); return 0; }