HNOI2008 水平可見直線

2022-04-08 02:08:18 字數 1568 閱讀 5268

luogu

給定若干條直線 (都是 \(y = ax + b\) 的形式)

求從上往下看所有可以看到的直線,從小往大輸出編號

\(n \le 50000\),\(|a|,|b| \le 500000\)

從上往下看,若干條直線構成的半平面交的部分才是可見的

聽說直接做半平面交可以 \(o(n \log n)\) 做,但是我不會

\(y = kx + b\),對於乙個 \(x\),只有最大的那乙個 \(y\) 才可以被看到

換一種形式看這條直線 : \(-kx + y = b\)

由於 \(-k\) 和 \(b\) 是固定的,所以可以先把它看成乙個定點\((-k, b)\)

對於每乙個 \(x\),我們要求最大的 \(y\)

把 \(x\) 看作是斜率,則 \(y\) 就是 \(y\) 軸上的截距

發現對於所有的定點 \((-k, b)\) ,只有在(上)凸包的點是有用的

(偽)證明 : 想象一條斜率為 \(x\) 的直線從上往下去靠,靠到第乙個點時 \(y\) 軸截距最大,這個靠到第乙個點肯定是凸包上的點

那直接對點集 \((-k, b)\) 求上凸包就完了

\(\color \)

我這份**在 bzoj 上過了,但在 luogu 上過不了,窩佛了

/*

從上往下看, 若干條直線構成的半平面交的部分是可見的

y = kx + b

轉化成對偶問題, 求上凸包, 只有凸包上的點才是可見的

-kx + y = b

相當於對於不同的 x, 要求最大的 y

*/#include #define n 50005

using namespace std;

typedef long long ll;

int n;

int stk[n];

bool vis[n];

struct vec

vec operator + (const vec &t) const

vec operator - (const vec &t) const

bool operator < (const vec &rhs) const

}a[n];

mapid;

inline ll crop(const vec &u, const vec &v)

int main()

sort(a + 1, a + n + 1, less());

int top = 0;

for(int i = 1; i <= n; ++i)

for(int i = 1; i <= top; ++i)

vis[id[a[stk[i]]]] = true;

for(int i = 1; i <= n; ++i)

if(vis[i])

printf("%d ", i);

putchar('\n');

return 0;

}

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 條直...

HNOI 2008 水平可見直線

傳送門 題目描述 在 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 為被覆蓋的。例如...

HNOI2008 水平可見直線

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