线段相交——toj 1770 Pick_up sticks
题目大意:
有一堆棍子,一个一个扔到一个平面上,存在某些棍子上面没有任何棍子,那么我们就说这样的棍子在顶上。按照往平面上扔棍子的顺序给出每个棍子端点坐标。求所有在顶上的棍子。
这是一个赤裸裸的求线段相交的问题。一般的,我们在判断两个线段是否相交时,要通过快速排斥实验和跨立实验来判定。快速排斥实验是说,每条线段都能决定一个四边分别与x,y轴平行的矩形,该线段是矩形的对角线。那么线段相交的必要条件是两个矩形有交集。跨立实验室说,在通过了快速排斥实验的情况下,两条线段相交的充要条件是任何一个线段的两个顶点跨立在另一条线段的两边。
那么,判断两个线段是否相交的函数可以写成这样:
1 inline bool intersect(PT s1,PT e1,PT s2,PT e2)
2 {
3 return((max(s1.x,e1.x)>=min(s2.x,e2.x)) &&
4 (max(s2.x,e2.x)>=min(s1.x,e1.x)) &&
5 (max(s1.y,e1.y)>=min(s2.y,e2.y)) &&
6 (max(s2.y,e2.y)>=min(s1.y,e1.y)) &&
7 (crossP(s1,e1,s2)*crossP(s1,e1,e2)<0) &&
8 (crossP(s2,e2,s1)*crossP(s2,e2,e1)<0));
9 }
2 {
3 return((max(s1.x,e1.x)>=min(s2.x,e2.x)) &&
4 (max(s2.x,e2.x)>=min(s1.x,e1.x)) &&
5 (max(s1.y,e1.y)>=min(s2.y,e2.y)) &&
6 (max(s2.y,e2.y)>=min(s1.y,e1.y)) &&
7 (crossP(s1,e1,s2)*crossP(s1,e1,e2)<0) &&
8 (crossP(s2,e2,s1)*crossP(s2,e2,e1)<0));
9 }
回到题目本身,最开始的思路是从后往前,最后一个棍子必然是在顶上的。维护一个top stick的集合,每个棍子都跟这个几何的元素比较,看是否相交。这个思路错在,有些棍子并不是直接被top stick 覆盖。所以,最后直接一个n2。