题意:
有一个二维坐标平面,有n(n<=50000)个导弹会从x轴上某一点p[i]发射,轨迹为抛物线,最高点坐标为(x[i],y[i])。(i表示第i个导弹)(p,x,y<=50000)
现在有m(m<=20000)架飞机要在这个二维平面上平行x轴飞行。每架飞机给两个数l,r(l,r<=n)表示这架飞机飞行的时候导弹l,l+1,...,r正在发射中。给定该飞机的飞行区间x0[j],x1[j](<=50000),求每架飞机从x0[j]飞到到x1[j]最小离地面多高才不会被导弹打中。(j表示第j架飞机)
思路:
其实就是一个简单的数学题。我们直接求出每个导弹的曲线方程a*x*x+b*x+c,然后根据飞机飞行的区间取最大值即可。
我们已知三个条件:
-b/(2*a)=x[i]
a*x[i]*x[i]+b*x[i]+c=y[i]
a*p[i]*p[i]+b*p[i]+c=0
三个方程解出三个未知数。
暴力的时间复杂度是n*n*m=5e13 给了10秒的时限 试了下居然580ms就过了。。。数据比较水,放心暴力。
#include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f using namespace std; const int mx=500010; int n,m,k; double max(double x,double y){if(x>y)return x;return y;} double min(double x,double y){if(x<y)return x;return y;} struct node{ double x,y; double p; double a,b,c; }dd[mx]; double ans[mx],tmp,cnt; int main() { ios::sync_with_stdio(false); int flag; int T=0; while(cin>>n) { if(T) puts(""); T=1; for(int i=1;i<=n;i++) { cin>>dd[i].p>>dd[i].x>>dd[i].y; tmp=dd[i].y/(dd[i].x*dd[i].x+dd[i].p*dd[i].p-2*dd[i].x*dd[i].p); dd[i].a=-tmp; dd[i].b=2*dd[i].x*tmp; dd[i].c=dd[i].y-dd[i].x*dd[i].x*tmp; } cin>>m; int mm=m; memset(ans,0,sizeof(ans)); int ii,jj; double xx,yy; int t=0; while(mm--) {t++; cin>>ii>>jj>>xx>>yy; for(int i=ii;i<=jj;i++) { double l=dd[i].p,r=2*dd[i].x-dd[i].p; if(xx>r||yy<l) continue; if(dd[i].x>=xx&&dd[i].x<=yy) { ans[t]=max(ans[t],dd[i].y); continue; } if(dd[i].x>yy) { tmp=dd[i].a*yy*yy+dd[i].b*yy+dd[i].c; ans[t]=max(ans[t],tmp); } if(dd[i].x<xx) { tmp=dd[i].a*xx*xx+dd[i].b*xx+dd[i].c; ans[t]=max(ans[t],tmp); } } } for(int i=1;i<=m;i++) cout<<fixed<<setprecision(9)<<ans[i]<<endl; } return 0; }