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.

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 }
View Code

 

posted @ 2019-03-21 14:58  zjxxcn  阅读(169)  评论(0编辑  收藏  举报