题解/算法 {\2957. 赛车}
LINK: https://www.acwing.com/problem/content/2960/
;
#提示#: t=0
起始时刻 也算作答案;
#题意转换#: 即若干个k,b >=0
的直线,
∀
x
≥
0
\forall x \geq 0
∀x≥0 对于一个直线L 如果他的y值
L
(
x
)
L(x)
L(x) 是
≥
\geq
≥其他所有直线的y值, 那么这个L直线 要记录到答案里;
将直线看做是 (方向朝右上的)有向直线后, 求出半平面交(一定是无限区域(单开口)类型) 那么所有与半平面交 在
x
≥
0
x\geq 0
x≥0处 有接触的 有向边 就是答案;
.
一种做法可以这样直接做, 然后再去特判 把处在
x
<
0
x < 0
x<0区域的有向边 给去掉; 但这比较麻烦;
更简洁的做法是: 添加一个辅助边 方向朝下的Y轴, 此时 半平面交一定是在第一象限, 最终求出的答案(一定包含这个辅助边) 除了这个辅助边 剩下的都是答案;
由于算法会进行去重 而答案会出现重复边, 因此 你需要对重复边 进行记录; 使用map< DirectedLine, vector<int>>
存储所有重复的有向边;
map< __Geometry2D::DirectedLine, vector<int> > Mp;
void Add_directedLine( const __Geometry2D::DirectedLine & _directedLine){ // 该有向直线的*左侧区域*为目标区域
Mp[ _directedLine].push_back( __DirectedLines.size()); // 存储重复边
}
vector< int> ANS;
for( auto i = QueHead; i <= QueTail; ++i){
auto t = Mp[ get<0>( __DirectedLines[ Que[i]])];
for( auto j : t){
if( j >= 1) // 辅助边的ID号为`0`, 其他的为`> 0`;
ANS.push_back( j);
}
}