http://acm.hdu.edu.cn/showproblem.php?pid=5032
给定一个1000x1000的点阵,m组询问,每次询问一个由(0,0)、(x,0)点一以及从原点出发的方向向量(a,b)构成的直角三角形包围的点的权值和。
先把1000x1000个点离线出极角关系,然后对m个询问按极角排序,不停add,遇到询问的极角就query一次前缀和
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define clr0(x) memset(x,0,sizeof(x)) typedef long long LL; int A,B,m; struct point{ int x,y; LL ans; double p; }s[1000005],sc[100005]; bool cmpp(point a,point b) { return a.p < b.p; } bool cmpid(point a,point b) { return a.y < b.y; } LL bit[1005]; void add(int x,LL v) { for(int i = x;i <= 1000;i += (i&-i)) bit[i] += v; } LL query(int x) { LL ans = 0; for(int i = x;i >= 1;i -= (i&-i)) ans += bit[i]; return ans; } int main(){ int _,cnt = 0,cas = 1,x,a,b; RD(_); for(int i = 1;i <= 1000;++i) for(int j = 1;j <= 1000;++j){ s[cnt++] = (point){i,j,0,1.0*j/i}; } sort(s,s+cnt,cmpp); while(_--){ RD2(A,B); RD(m); for(int i = 0;i < m;++i){ RD2(a,b);RD(x); sc[i] = (point){x,i,0,1.0*b/a}; } sort(sc,sc+m,cmpp); clr0(bit); int now = 0; for(int i = 0;i < m;++i){ while(s[now].p <= sc[i].p){ add(s[now].x,(LL)(s[now].x + A)*(s[now].y + B)); now++; } sc[i].ans = query(sc[i].x); } sort(sc,sc+m,cmpid); printf("Case #%d:\n",cas++); for(int i = 0;i < m;++i) //cout<<sc[i].ans<<endl; printf("%I64d\n",sc[i].ans); } return 0; }