bzoj 1573: [Usaco2009 Open]牛绣花cowemb
Description
Bessie学会了刺绣这种精细的工作。牛们在一片半径为d(1 <= d <= 50000)的圆形布上绣花. 它们一共绣了N (2 <= N <= 50000)条直线,每条直线连接布的边缘上的两个点(没有两条线通过边上同一个点)。 作为一只热爱数学的牛,Bessie 知道每条线的公式, ax + by + c = 0. a, b, 和 c 为整数(-1000000 <= a <= 1000000; -1000000 <= b <= 1000000; -1000000 <= c <= 1000000).没有两条线完全重合。 不幸的是, 一部分线不通过圆布的内部. 原点(0,0)在布的正中央, 所有边上的点离原点距离为d. 每条线的公式满足至少a,b中的一个非零. 对于牛来说,刺绣作品中线的交点越多,便越有价值。帮助Bessie计算在圆中相交的线的对数,也就是说交点与原点的距离小于d。注意如果三条线在圆内同一点相交,这算3对线。4线共点->6对线.
Input
第1行: 两个空格分开的数, N 和 d 第2..N+1行: 第 i+1 行包含第i条线的参数: a, b 和 c
Output
第1行: 一行,包含一个数,为在园内相交的线的对数.
Sample Input
2 1
1 0 0
0 1 0
输入说明:
两条直线x=0和y=0.
1 0 0
0 1 0
输入说明:
两条直线x=0和y=0.
Sample Output
1
HINT
两条线在(0,0)相交, 明显离原点距离小于1.
思路:本题描述有有误,有些直线会不和圆相交,有些直线只会和圆相切,这些情况都要去掉,用点到直线的距离公式判断。$\frac{|ax+by+c|}{a^2+b^2}$。
接下来我们把每条直线和圆相交的两个点都算出来,算出他们的极角,并在另外一个数组里面对极角进行排序。
两条直线相交,一个极角是x和y,一个极角是a,b,那么一定要满足 $x<a<y<b$ 或者 $a<x<b<y$。这个可以通过维护一棵权值线段树实现。
时间复杂度$O(nlogn)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define rep(i,a,b) for(R i=a;i<=b;i++) 5 #define Rep(i,a,b) for(R i=a;i>=b;i--) 6 #define ms(i,a) memset(a,i,sizeof(a)) 7 #define gc() getchar() 8 #define mid (l+r>>1) 9 #define lc (x<<1) 10 #define rc (x<<1|1) 11 template<class T>void read(T &x){ 12 x=0; char c=0; int w=0; 13 while (!isdigit(c)) w+=c=='-',c=gc(); 14 while (isdigit(c)) x=x*10+(c^48),c=gc(); 15 if(w) x=-x; 16 } 17 int const N=50000+3; 18 double const eps=1e-6; 19 double const pi=acos(-1.0); 20 struct line{ 21 double a,b,c,t1,t2; 22 int x,y; 23 bool operator <(const line &rhs) const {return x<rhs.x; } 24 }p[N]; 25 double d,t[N<<1]; 26 int n,s[N<<3]; 27 int query(int x,int l,int r,int ll,int rr){ 28 if(ll>rr) return 0; 29 if(ll<=l && r<=rr) return s[x]; 30 int t1=0,t2=0; 31 if(ll<=mid) t1=query(lc,l,mid,ll,rr); 32 if(rr>mid) t2=query(rc,mid+1,r,ll,rr); 33 return t1+t2; 34 } 35 void update(int x,int l,int r,int p){ 36 if(l==r){s[x]++; return ;} 37 if(p<=mid) update(lc,l,mid,p); 38 else update(rc,mid+1,r,p); 39 s[x]=s[lc]+s[rc]; 40 } 41 int main(){ 42 read(n); 43 read(d); 44 rep(i,1,n) read(p[i].a),read(p[i].b),read(p[i].c); 45 int m=0; 46 rep(i,1,n){ 47 double ta=p[i].a*p[i].a+p[i].b*p[i].b; 48 double tb=2*p[i].b*p[i].c; 49 double tc=p[i].c*p[i].c-p[i].a*p[i].a*d*d; 50 long long C=p[i].c; 51 long long A=p[i].a; 52 long long B=p[i].b; 53 long long D=d; 54 if (C*C>=D*D*(A*A+B*B)) continue; 55 double dt=tb*tb-4*ta*tc; 56 if(fabs(dt)<eps){ 57 double y1=-tb/(2*ta); 58 double x1=sqrt(d*d-y1*y1); 59 double y2=y1; 60 double x2=-x1; 61 double z1=atan2(y1,x1); 62 double z2=atan2(y2,x2); 63 p[i].t1=min(z1,z2); 64 p[i].t2=max(z1,z2); 65 p[++m]=p[i]; 66 t[2*m-1]=p[i].t1; 67 t[2*m]=p[i].t2; 68 }else if(dt>-eps) { 69 double y1=(-tb+sqrt(dt))/(2*ta); 70 double x1=(-p[i].b*y1-p[i].c)/p[i].a; 71 double y2=(-tb-sqrt(dt))/(2*ta); 72 double x2=(-p[i].b*y2-p[i].c)/p[i].a; 73 double z1=atan2(y1,x1); 74 double z2=atan2(y2,x2); 75 p[i].t1=min(z1,z2); 76 p[i].t2=max(z1,z2); 77 p[++m]=p[i]; 78 t[2*m-1]=p[i].t1; 79 t[2*m]=p[i].t2; 80 } 81 } 82 n=m; 83 sort(t+1,t+2*n+1); 84 rep(i,1,n){ 85 p[i].x=lower_bound(t+1,t+2*n+1,p[i].t1)-t; 86 p[i].y=lower_bound(t+1,t+2*n+1,p[i].t2)-t; 87 } 88 sort(p+1,p+n+1); 89 long long ans=0; 90 rep(i,1,n){ 91 ans+=query(1,1,2*n,p[i].x+1,p[i].y-1); 92 update(1,1,2*n,p[i].y); 93 } 94 cout<<ans<<endl; 95 return 0; 96 }