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\n", ans[i] ? "Yes" : "No" ); 194 } 195 }