题意:
给定一个 [1, 1000] x [1, 1000] 的点阵,每个点阵中的点有一个权值。
n 组询问,每次询问一个由 (0,0)、(x,0) 点一以及从原点出发的方向向量 (a,b) 构成的直角三角形包围的点的权值和。
思路:
极角排序 + 离线处理 + 树状数组
这篇题解很详细
const double EPS = 1e-12;
struct Node {
int x, id;
double f;
bool operator < (const Node& rhs) const {
return f + EPS < rhs.f;
}
};
Node pts[N], queries[N];
LL ans[N];
int val[N];
int main() {
int n = 0;
rep(i, 1, 1000) rep(j, 1, 1000) {
pts[n] = (Node) {i, n, j * 1.0 / i };
++ n;
}
int t, cas = 0, A, B, q;
scanf("%d", &t);
while ( t -- ) {
scanf("%d%d%d", &A, &B, &q);
rep(i, 1, 1000) rep(j, 1, 1000) {
int pos = (i - 1) * 1000 + j - 1;
val[pos] = (i + A) * (j + B);
}
rep(i, 0, q-1) {
int a, b, x;
scanf("%d%d%d", &a, &b, &x);
queries[i] = (Node) {x, i, b * 1.0 / a};
}
sort(pts, pts + n);
sort(queries, queries + q);
BIT::init();
int now = 0;
for (int i = 0; i < q; ++ i) {
while ( now < n && pts[now].f < queries[i].f + EPS ) {
BIT::update(pts[now].x, val[pts[now].id]);
++ now;
}
ans[ queries[i].id ] = BIT::sum( queries[i].x );
}
printf("Case #%d:\n", ++ cas);
for (int i = 0; i < q; ++ i) printf("%I64d\n", ans[i]);
}
return 0;
}