【计几】cf1359F(edu88)RC Kaboom Show
题目链接:http://codeforces.com/contest/1359/problem/F
题意:给你25000个点,每个点有各自的方向以及速度,问最少需要多少时间使得发生碰撞(两点同一位置),注意点的出发时间任选。
做法:很容易想到,三分时间,然后判断n条线段是否存在交点,然后我就不会了。
看了别人的代码发现,用set维护线段相对位置,这像极了我之前的一道题(https://www.cnblogs.com/xiaobuxie/p/12642374.html第十题)
首先定义两个线段的大小关系:在下方的线段是小的,如果两个线段相交,就以交点左边,下方的线段为小。
然后画图可以发现这个大小关系是可以传递的,所以我们可以用set来维护这个东西。之前那题是极角的扫描线,这题则是竖直的扫描线。
然后我们把线段的端点排个序,按照左端点插入线段,右端点删除线段那样维护这个set,然后我们可以发现,两个线段s1 和 s2 相交的话,假设s1 > s2 有两种情况:
第一种情况:set里面s1 和 s2 是相邻的,那么我们只需要在插入每个线段的时候,判断它 和它相邻的线段 是否相交即可。
第二种情况:set里面 s1 和 s2 不相邻,也就是说有某些线段卡在s1和s2中间,这些线段中假如 a 和s1相交的,那么 s2 = max(s2,a ) , 假如和 s2 相交, s1 = min(s1,a),也就是说我们肯定能找到相交的两个线段 s1和s2,使得不存在 s1 到s2 之间的线段和 s1或者s2相交。
然后我们可以发现这些线段会卡在 s1 和 s2 以及 s1s2的交点 所形成的区间内, 那么对于这些线段中最后删除的一个线段,寻找它的pre 和 nex (也就是s2 和 s1 ) ,判断相交即可。
坑点:用long double 。。。。上一题set也是用long double 才能过,然后注意精度。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 25000+9; 4 #define eps 1e-10 5 #define ld long double 6 int sgn(ld x){ 7 if( fabs(x) < eps ) return 0; 8 if(x<0) return -1; 9 return 1; 10 } 11 struct Point{ 12 ld x,y; 13 Point operator + (const Point& b)const{ 14 return (Point){x+b.x,y+b.y}; 15 } 16 Point operator - (const Point& b)const{ 17 return (Point){x-b.x,y-b.y}; 18 } 19 Point operator * (const ld& b)const{ 20 return (Point){x*b,y*b}; 21 } 22 Point operator / (const ld& b)const{ 23 return (Point){x/b,y/b}; 24 } 25 ld len(){ 26 return sqrt(x*x+y*y); 27 } 28 bool operator <(const Point& b)const{ 29 if( x==b.x ) return x < b.y; 30 return x < b.x; 31 } 32 bool operator == (const Point& b)const{ 33 return x==b.x && y==b.y; 34 } 35 }p[N],dir[N]; 36 struct Seg{ 37 Point s,t; 38 ld gety(ld x)const{ 39 if( fabs(t.x-s.x ) < eps ) return t.y; 40 return s.y + (t.y-s.y) * (x-s.x)/(t.x-s.x); 41 } 42 43 }seg[N]; 44 set<Seg> sgs; 45 bool operator < ( const Seg& a,const Seg& b){ 46 ld xp = max(a.s.x,b.s.x); 47 ld ya = a.gety(xp) , yb = b.gety(xp); 48 if(fabs(ya-yb)<eps){ 49 if( fabs(a.s.x-b.s.x)<eps ) return a.t.x<b.t.x-eps; 50 return a.s.x<b.s.x-eps; 51 } 52 return ya < yb; 53 } 54 ld speed[N]; 55 int n; 56 ld cross(Point a,Point b){ 57 return a.x*b.y - b.x*a.y; 58 } 59 //两线段是否相交 60 bool insert(Seg l1,Seg l2){ 61 return 62 max(l1.s.x,l1.t.x) >= min(l2.s.x,l2.t.x) && 63 max(l2.s.x,l2.t.x) >= min(l1.s.x,l1.t.x) && 64 max(l1.s.y,l1.t.y) >= min(l2.s.y,l2.t.y) && 65 max(l2.s.y,l2.t.y) >= min(l1.s.y,l1.t.y) && 66 sgn( cross( l2.s-l1.s,l1.t-l1.s) ) * sgn( cross( l2.t-l1.s,l1.t-l1.s) )<=0 && 67 sgn( cross( l1.s-l2.s,l2.t-l2.s) ) * sgn( cross( l1.t-l2.s,l2.t-l2.s) )<=0; 68 } 69 bool pre(set<Seg>::iterator it,set<Seg>::iterator& res){ 70 if(it == sgs.begin()) return 0; 71 res = --it; 72 return 1; 73 } 74 bool nex(set<Seg>::iterator it,set<Seg>::iterator& res){ 75 res = ++it; 76 if( res == sgs.end() ) return 0; 77 return 1; 78 } 79 bool judge(double tim){ 80 vector< pair<Point,int> > pts; 81 for(int i = 1;i<=n;++i){ 82 seg[i].s = p[i]; 83 seg[i].t = p[i] + dir[i] * speed[i] * tim/dir[i].len(); 84 if(seg[i].t < seg[i].s ) swap(seg[i].s,seg[i].t); 85 pts.push_back({seg[i].s,i}); 86 pts.push_back({seg[i].t,-i}); 87 } 88 sort(pts.begin(),pts.end()); 89 sgs.clear(); 90 for(int i = 0;i<pts.size();++i){ 91 int id = pts[i].second; 92 93 if(id>0){ 94 sgs.insert(seg[id]); 95 set<Seg>::iterator it = sgs.lower_bound(seg[id]); 96 97 set<Seg>::iterator tem; 98 if(pre(it,tem)){ 99 if(insert(seg[id],(*tem))){ 100 return 1; 101 } 102 } 103 if(nex(it,tem)){ 104 if( insert(seg[id],(*tem))) return 1; 105 } 106 } 107 else{ 108 id = -id; 109 set<Seg>::iterator it = sgs.lower_bound(seg[id]); 110 set<Seg>::iterator le , ri; 111 if( pre(it,le) && nex(it,ri) ){ 112 if( insert((*le),(*ri) ) )return 1; 113 } 114 sgs.erase(it); 115 } 116 } 117 return 0; 118 } 119 int main(){ 120 cout << setprecision(10) << fixed; 121 cin>>n; 122 for(int i = 1;i<=n;++i){ 123 cin>>p[i].x>>p[i].y>>dir[i].x>>dir[i].y>>speed[i]; 124 } 125 ld l = 0, r = 1e12,res = -1; 126 for(int cas = 1;cas<=60;++cas){ 127 ld m = (l+r)/2; 128 if(judge(m)){ 129 res = m; 130 r = m; 131 } 132 else l = m; 133 } 134 if(res == -1) puts("No show :("); 135 else cout<<res<<endl; 136 }