HNOI 2008 水平可見直線

2021-08-29 07:13:21 字數 2138 閱讀 4184

傳送門

題目描述:

在 xo

yxoy

xoy 直角座標平面上有 n

nn 條直線 l1,

l2,.

..,l

nl_1,l_2,...,l_n

l1​,l2

​,..

.,ln

​,若在 y

yy 值為正無窮大處往下看,能見到 l

il_i

li​ 的某個子線段,則稱 l

il_i

li​ 為可見的,否則 l

il_i

li​ 為被覆蓋的。

例如,對於直線 l

1l_1

l1​:y=x

y=xy=

x;l2

l_2l2

​:y=−x

y=-x

y=−x

;l

3l_3

l3​:y=0

y=0y=

0,則 l

1l_1

l1​ 和 l

2l_2

l2​ 是可見的,l

3l_3

l3​ 是被覆蓋的。給出 n

nn 條直線,表示成 y=a

x+

by=ax+b

y=ax+b

的形式(∣a∣

,∣b∣

|a|,|b|

∣a∣,∣b

∣ ≤ 500000

500000

500000

),且 n

nn 條直線兩兩不重合。求出所有可見的直線.

輸入格式:

第一行為 nnn(

0<

n<

50000

)(0 < n < 50000)

(0<

n<50

000)

,接下來的 n

nn 行輸入 ai,

bi

a_i,b_i

ai​,bi

輸出格式:

從小到大輸出可見直線的編號,兩兩中間用空格隔開,最後乙個數字後面也必須有個空格

樣例資料:輸入

3-1 0

1 00 0 輸出

1 2

其實看這道題的題意,應該還是很容易可以想到半平面交吧

還是按照斜率大小排序,每次加新線的時候就比較一下交點位置,然後判斷是否需要彈掉棧頂

不過這道題比半平面交模板不同的是不用彈掉隊首和隊尾(因為它們肯定能被看見)

注意這道題有平行線的情況,我們只用保留 b

bb 值最大的那條

#include

#include

#include

#include

#define n 50005

#define eps 1e-8

using

namespace std;

struct line

l[n]

,sta[n]

;bool

comp1

(const line &p,

const line &q)

bool

comp2

(const line &p,

const line &q)

double

interx

(line a,line b)

intmain()

sort

(l+1

,l+n+

1,comp1)

;int num=

0,top=0;

sta[

++top]

=l[1];

for(i=

2;i<=n;

++i)

sort

(sta+

1,sta+top+

1,comp2)

;for

(i=1

;i<=top;

++i)

printf

("%d "

,sta[i]

.id)

;return0;

}

HNOI 2008 水平可見直線

hnoi 2008 水平可見直線 在 xoy 直角座標平面上有n條直線 l1,l2,ln,若在y 值為正無窮大處往下看,能見到 li的某個子線段,則稱 li為可見的,否則 li為被遮蓋的。例如,對於直線 l1 y x l2 y x l3 y 0 則 l1和l2是可見的,l3是被遮蓋的。給出 n 條直...

HNOI2008 水平可見直線

luogu 給定若干條直線 都是 y ax b 的形式 求從上往下看所有可以看到的直線,從小往大輸出編號 n le 50000 a b le 500000 從上往下看,若干條直線構成的半平面交的部分才是可見的 聽說直接做半平面交可以 o n log n 做,但是我不會 y kx b 對於乙個 x 只...

HNOI2008 水平可見直線

傳送門 這道題我自己想了想 不過並沒有想出什麼很好的方法。我們簡單一點考慮,問題可以轉化成求所有在最上面的直線的那個集合中有哪些直線。我們知道斜率最大 接近正無窮 和斜率最小 接近負無窮 的是肯定要被保留下來的,而且還是在最兩側的兩條直線。那麼對於一般的直線,我們考慮一下。如上圖,這兩條直線都是可見...