1. 程式人生 > >BZOJ1573: [Usaco2009 Open]牛繡花cowemb

BZOJ1573: [Usaco2009 Open]牛繡花cowemb

abs add class stream isp blog opened 如果能 。。

求半徑d<=50000的圓(不含邊界)內n<=50000條直線有多少交點,給直線的解析式。

一開始就想,如果能求出直線交點與原點距離<d的條件,那麽從中不重復地篩選即可。然而兩個kx+b聯立起來加勾股定理特別醜。。

換個想法,一條線在圓上就截了兩個點。把這些點做極角排序後(即從y軸正半軸的射線順時針掃一圈,把依次遇到的點排下來)後,每條直線就可以兩個點表示。設其極角排序後,序較小的那個點叫A,另一個叫B。

其實就是:對所有(Ai,Bi),求有多少j滿足Aj<Ai且Ai<Bj<Bi,其中小於號是極角序比較。

這就好比:給若幹線段,求有多少對線段相交而不包含。也就是對所有Li,Ri,求有多少Lj<Li並且Li<Rj<Ri。也就是,把原來一條直線看成兩個點,兩個點按極角序編號,兩個點間的弧的交拉直成線段交,求這些線段有多少對交,就變成很裸的掃描線。

技術分享
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 #include<stdlib.h>
  5 #include<math.h>
  6 //#include<iostream>
  7 using namespace std;
  8  
  9 int n,d;
 10 #define maxn 100011
 11 const double eps=1e-10,inf=1e15;
 12 struct Line
 13 {
 14
double k,b; 15 }a[maxn]; 16 struct Point 17 { 18 double x,y,t;int k,id; 19 bool operator < (const Point &b) const 20 {return k<b.k || (k==b.k && t>b.t);} 21 bool operator == (const Point &b) const 22 {return fabs(x-b.x)<eps && fabs(y-b.y)<eps;}
23 bool operator != (const Point &b) const {return !(*this==b);} 24 }p[maxn];int lp=0; 25 double x,y,z; 26 #define LL long long 27 void addp(double x,double y,int id) 28 { 29 Point &e=p[++lp]; 30 e.x=x;e.y=y;e.id=id; 31 e.t=x?y/x:inf; 32 if (x>=0 && y>0) e.k=1; 33 else if (x>0 && y<=0) e.k=2; 34 else if (x<=0 && y<0) e.k=3; 35 else e.k=4; 36 } 37 void makep(int x) 38 { 39 if (a[x].k==inf) 40 { 41 if (a[x].b-d>eps || a[x].b+d<-eps) return; 42 addp(a[x].b,sqrt(1.0*d*d-a[x].b*a[x].b),x); 43 addp(a[x].b,-sqrt(1.0*d*d-a[x].b*a[x].b),x); 44 } 45 else 46 { 47 double u=a[x].k*a[x].k+1,v=2*a[x].k*a[x].b,w=a[x].b*a[x].b-d*d; 48 if (v*v-4*u*w<-eps) return; 49 double tmp=(-v+sqrt(v*v-4*u*w))/(2*u); 50 addp(tmp,a[x].k*tmp+a[x].b,x); 51 tmp=(-v-sqrt(v*v-4*u*w))/(2*u); 52 addp(tmp,a[x].k*tmp+a[x].b,x); 53 } 54 } 55 struct BIT 56 { 57 int a[maxn],n; 58 void clear(int n) {memset(a,0,sizeof(a));this->n=n;} 59 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 60 int query(int x) {int ans=0;for (;x;x-=x&-x) ans+=a[x];return ans;} 61 }t; 62 struct seg 63 { 64 int l,r; 65 bool operator < (const seg &b) const {return l<b.l;} 66 }b[maxn]; 67 bool vis[maxn]; 68 int main() 69 { 70 scanf("%d%d",&n,&d); 71 for (int i=1;i<=n;i++) 72 { 73 scanf("%lf%lf%lf",&x,&y,&z); 74 a[i].k=y?-x/y:inf; 75 a[i].b=y?-z/y:-z/x; 76 makep(i); 77 } 78 sort(p+1,p+1+lp); 79 memset(vis,0,sizeof(vis)); 80 p[lp+1].x=inf;p[lp+1].y=inf; 81 int cnt=0,last=1; 82 for (int i=2;i<=lp+1;i++) if (p[i]!=p[i-1]) 83 { 84 cnt++; 85 for (int &j=last;j<i;j++) 86 if (vis[p[j].id]) b[p[j].id].r=cnt; 87 else vis[p[j].id]=1,b[p[j].id].l=cnt; 88 } 89 for (int i=1;i<=n;i++) if (!vis[i]) b[i].l=b[i].r=0x3f3f3f3f; 90 sort(b+1,b+1+n); 91 LL ans=0;last=1; 92 t.clear(cnt); 93 for (int i=2;i<=(lp>>1)+1;i++) if (b[i].l!=b[i-1].l) 94 { 95 for (int j=last;j<i;j++) 96 ans+=t.query(b[j].r-1)-t.query(b[j].l); 97 for (int &j=last;j<i;j++) 98 t.add(b[j].r,1); 99 } 100 printf("%lld\n",ans); 101 return 0; 102 }
View Code

BZOJ1573: [Usaco2009 Open]牛繡花cowemb