bzoj 2961

根据“点在圆内”关系,列出点P(x0,y0)在圆C(x,y)内的关系:

(x-x0)^2+(y-y0)^2 <= x^2+y^2

化简得:

2*x0*x+2*y0*y >= x0^2+y0^2

然后我们就可以把一个点当成一条线,一个圆当成一个点,通过上面的表达式来转换,这样“点在圆内”的关系就转化成了“点在半平面内”的关系。这样原问题就转化成了不断的加点,然后询问是否所有点都在某个半平面中。

这个东西因为“某一个点在不在半平面中”对”所有点都在半平面中“的答案贡献独立(前者拥有一票否决权),又没有强制在线,所以可以使用对时间分治的思想,以多一个log的复杂度将”边加点边询问问题“变成”先把所有点都加进去,再询问问题“,而后者可以在O(nlogn)时间复杂度内搞定,所以可以在O(nloglog)的时间复杂度内解决。

这道题开始看错题的限制了,题目中限制的是圆心坐标的范围,没有限制询问点坐标的范围,所以就挂了。

  1 /**************************************************************
  2     Problem: 2961
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:6708 ms
  7     Memory:96872 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cmath>
 12 #include <vector>
 13 #include <algorithm>
 14 #define N 500010
 15 #define eps 1e-10
 16 using namespace std;
 17  
 18 int sg( double x ) { return (x>-eps)-(x<eps); }
 19 struct Vector {
 20     double x, y;
 21     void read() { 
 22         scanf( "%lf%lf", &x, &y ); 
 23     }
 24     Vector(){}
 25     Vector( double x, double y ):x(x),y(y){}
 26     Vector operator+( const Vector &b ) const { return Vector(x+b.x,y+b.y); }
 27     Vector operator-( const Vector &b ) const { return Vector(x-b.x,y-b.y); }
 28     Vector operator*( double b ) const { return Vector(x*b,y*b); }
 29     Vector operator/( double b ) const { return Vector(x/b,y/b); }
 30     double operator^( const Vector &b ) const { return x*b.y-y*b.x; }
 31     double operator&( const Vector &b ) const { return x*b.x+y*b.y; }
 32     double ang() { return atan2l(y,x); }
 33     bool operator<( const Vector &b ) const {
 34         return sg(x-b.x)<0 || (sg(x-b.x)==0 && sg(y-b.y)<0);
 35     }
 36 };
 37 typedef Vector Point;
 38 struct Line {
 39     Point p;
 40     Vector u;
 41     double ang;
 42     int id;
 43     bool ok;
 44     void read( int id ) {
 45         double x, y;
 46         double a, b, c;
 47         scanf( "%lf%lf", &x, &y );
 48         a=x+x, b=y+y;
 49         c=x*x+y*y;
 50  
 51         if( sg(a)==0 && sg(b)==0 ) {
 52             p.x = p.y = 0.0;
 53             u.x = 1.0;
 54             u.y = 0.0;
 55         } else {
 56             if( sg(a)!=0 ) 
 57                 p.x = c/a, p.y = 0.0;
 58             else
 59                 p.x = 0.0, p.y = c/b;
 60             u.x = -b, u.y = a;
 61             if( sg(u^(Point(0.0,0.0)-p))>=0 ) 
 62                 u.x=-u.x, u.y=-u.y;
 63         }
 64  
 65         ok = true;
 66         this->id = id;
 67         ang = u.ang();
 68     }
 69 };
 70 struct Job {
 71     int opt;
 72     Point pt;
 73     Line ln;
 74     void read( int id ) {
 75         scanf( "%d", &opt );
 76         if( opt==0 ) pt.read();
 77         else ln.read(id);
 78     }
 79 };
 80  
 81 int n;
 82 Job job[N];
 83 int ans[N];
 84 Point cvx[N]; 
 85 double lang[N];
 86  
 87 bool onleft( Line &l, Point &p ) {  //  <=
 88     return sg( l.u^(p-l.p) ) >= 0;
 89 }
 90 bool onleft( Point &a, Point &b, Point &p ) {   //  <
 91     return sg( (b-a)^(p-a) ) > 0;
 92 }
 93 int convex( vector<Point> &p ) {
 94     sort( p.begin(), p.end() );
 95     int n=p.size();
 96     int m;
 97     cvx[m=0] = p[0];
 98     for( int i=1; i<n; i++ ) {
 99         while( m>0 && !onleft(cvx[m-1],cvx[m],p[i]) ) m--;
100         cvx[++m] = p[i];
101     }
102     int k=m;
103     for( int i=n-2; i>=0; i-- ) {
104         while( m>k && !onleft(cvx[m-1],cvx[m],p[i]) ) m--;
105         cvx[++m] = p[i];
106     }
107     return m;   //  n>=2
108 }
109 void binary( int lf, int rg, vector<Point> &vp, vector<Line> &vn ) {
110     if( lf==rg ) {
111         if( job[lf].opt==0 ) 
112             vp.push_back( job[lf].pt );
113         else
114             vn.push_back( job[lf].ln );
115         return;
116     }
117     vector<Point> lvp;
118     vector<Line> rvn;
119     int mid=(lf+rg)>>1;
120     binary( lf, mid, lvp, vn );
121     binary( mid+1, rg, vp, rvn );
122     //--
123     Point kpt;
124     if( lvp.empty() || rvn.empty() ) {
125         //  do nothing
126     } else if( lvp.size()==1 ) {
127         for( int t=0; t<rvn.size(); t++ ) {
128             if( !rvn[t].ok ) continue;
129             if( !onleft(rvn[t],lvp[0]) ) 
130                 rvn[t].ok = false;
131         }
132     } else {
133         int n = convex( lvp );
134         for( int t=0; t<n; t++ )
135             lang[t] = (cvx[(t+1==n?0:t+1)]-cvx[t]).ang();
136         int vid = 0;
137         for( int t=0; t<n; t++ )
138             if( lang[t]>lang[(t+1==n?0:t+1)] ) {
139                 vid = (t+1==n?0:t+1);
140                 break;
141             }
142         rotate( cvx, cvx+vid, cvx+n );
143         rotate( lang, lang+vid, lang+n );
144         for( int t=0; t<rvn.size(); t++ ) {
145             if( !rvn[t].ok ) continue;
146             int tt;
147             if( rvn[t].ang<=lang[0] || rvn[t].ang>=lang[n-1] ) {
148                 tt = 0;
149             } else {
150                 int lf=1, rg=n-1;
151                 while( lf<rg ) {
152                     int mid=(lf+rg)>>1;
153                     if( lang[mid]>rvn[t].ang ) {
154                         rg = mid;
155                     } else {
156                         lf = mid+1;
157                     }
158                 }
159                 tt = lf;
160             }
161             int pt = tt==0?n-1:tt-1;
162             int nt = tt==n-1?0:tt+1;
163             if( !onleft(rvn[t],cvx[tt]) 
164               ||!onleft(rvn[t],cvx[pt])
165               ||!onleft(rvn[t],cvx[nt]) ) {
166                 rvn[t].ok=false;
167             }
168         }
169     }
170     //--
171     for( int t=0; t<lvp.size(); t++ )
172         vp.push_back( lvp[t] );
173     for( int t=0; t<rvn.size(); t++ )
174         vn.push_back( rvn[t] );
175 }
176 int main() {
177     scanf( "%d", &n );
178     bool ok = false;
179     for( int i=1; i<=n; i++ ) {
180         job[i].read(i);
181         job[i].ln.ok = ok;
182         if( job[i].opt==0 ) ok=true;
183     }
184     vector<Line> vn;
185     vector<Point> vp;
186     binary( 1, n, vp, vn );
187     for( int i=1; i<=n; i++ )
188         ans[i] = -1;
189     for( int t=0; t<vn.size(); t++ ) 
190         ans[vn[t].id] = vn[t].ok;
191     for( int i=1; i<=n; i++ ) {
192         if( ans[i]==-1 ) continue;
193         printf( "%s
", ans[i] ? "Yes" : "No" );
194     }
195 }
View Code
原文地址:https://www.cnblogs.com/idy002/p/4455435.html