# 【BZOJ4858】【JSOI2016】炸弹攻击 2

【题目链接】

【思路要点】

• 枚举发射源，将发射源当做原点，对敌人和激光塔极角排序。
• 由于敌人纵坐标均为正，而其它点均为负，因此每两个角度差在$$\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() {
for (int i = 1; i <= n; i++) {
a[i].type = true;
}
for (int i = 1; i <= m; i++)
int k; read(k); n += k;
for (int i = n - k + 1; i <= n; i++) {
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;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120