ZOJ3379 Master Spark
(¦3[____]← 扫描线问题,抛物线方程为 y=a*x*x 形式,
对每个点求出抛物线中轴的范围theta-delta~theta+delta,
theta = atan2(y,x),delta则用方程组可解x*x+y*y=z*z+(a*z*z)^2,tan(theta)=z/(a*z*z),故theta = atan2(1,a*z)
然后从-PI到PI进行扫描,用最小堆维护即可
这题调了好久啊,把>写成<,把double写成int。。。= =、捉鸡
#include<cstdio> #include<cmath> #include<cstring> #include<vector> #include<utility> #include<iostream> #include<algorithm> using namespace std; const int N=30010; const double TPI = 2*acos(-1); double x[N],y[N]; vector<pair<double,double> > ang; int cnt; double heap[N]; void heap_add(double a) { heap[++cnt]=a; int u,ch=cnt; double t=heap[cnt]; u = cnt>>1; while(u&&heap[u]>t) { heap[ch]=heap[u]; ch>>=1; u=ch>>1; } heap[ch]=t; } void heap_pop() { heap[1]=heap[cnt]; --cnt; int u=1,chl,chr,ch; double t=heap[1]; while(cnt) { chl=u<<1; chr=chl|1; if(chr<=cnt&&heap[chl]<heap[chr]) ch=chl; else if(chr<=cnt&&heap[chl]>heap[chr]) ch=chr; else if(chl<=cnt) ch=chl; else { heap[u]=t; break; } if(t>heap[ch]) { heap[u]=heap[ch]; u=ch; } else { heap[u]=t; break; } } } int main() { int n,ans; double a,theta,delta,z; while(scanf("%d%lf",&n,&a)==2) { ang.clear(); cnt = 0; for(int i=0;i<n;++i) scanf("%lf",x+i); for(int i=0;i<n;++i) scanf("%lf",y+i); for(int i=0;i<n;++i) { theta=atan2(y[i],x[i]); z=sqrt((sqrt(1+4*a*a*(x[i]*x[i]+y[i]*y[i]))-1)/(2*a*a)); delta = atan2(1,a*z); ang.push_back(make_pair(remainder(theta-delta,TPI),remainder(theta+delta,TPI))); if(ang.back().first>ang.back().second) { heap_add(ang.back().second); ang.back().second+=TPI; } } ans = cnt; sort(ang.begin(),ang.end()); for(vector<pair<double,double> >::iterator it=ang.begin();it!=ang.end();++it) { heap_add(it->second); while(cnt&&heap[1] < it->first) { heap_pop(); } ans=max(ans,cnt); } printf("%d daze\n",ans); } }