#include<bits/stdc++.h> #define debu using namespace std; typedef double DB; struct point { int flag; DB w; point(DB a=0.0,int b=0):w(a),flag(b) {} }; int n; DB w,h; vector<point> all; void make(DB px,DB py,DB vx,DB vy) { if(vx==0) if(px<=0||px>=w) return ; if(vy==0) if(py<=0||py>=h) return ; DB tmpl1=min(-px/vx,(w-px)/vx); DB tmpl2=max(-px/vx,(w-px)/vx); DB tmpr1=min(-py/vy,(h-py)/vy); DB tmpr2=max(-py/vy,(h-py)/vy); DB l=max(tmpl1,tmpr1); DB r=min(tmpl2,tmpr2); // cout<<l<<" "<<r<<endl; if(l>r) return ; all.push_back(point(l,0)); all.push_back(point(r,1)); } int cmp(point a,point b) { if(a.w==b.w) return a.flag>b.flag; else return a.w<b.w; } void solve() { int ans=0,tmp=0; sort(all.begin(),all.end(),cmp); /*for(int i=0;i<all.size();i++) cout<<all[i].w<<" "<<all[i].flag<<endl;*/ for(int i=0; i<all.size(); i++) { if(all[i].flag==0) { tmp++; ans=max(ans,tmp); } else tmp--; } printf("%d\n",ans); } int main() { #ifdef debug freopen("in.in","r",stdin); #endif // debug int t; scanf("%d",&t); while(t--) { all.clear(); scanf("%lf%lf",&w,&h); scanf("%d",&n); for(int i=0; i<n; i++) { DB px,py,vx,vy; scanf("%lf%lf%lf%lf",&px,&py,&vx,&vy); // cout<<px<<" "<<py<<" "<<vx<<" "<<vy<<endl; make(px,py,vx,vy); } solve(); // cout<<"************************"<<endl; } return 0; }
题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1906
题解:求出各个流星到达区域内的时间范围(l,r),则问题转化为求一个数t,使得t被包含在最多的区间。所以每次遇到一个左端点,ans++并更新;否则若为右端点ans--。注意有左端点与右端点相等时先处理右端点(将所有端点记录,flag==1代表右端点,flag==0代表左端点,全部加入vector排序时flag作为第二关键字即可)。注意vx或vy等于0时的情况。