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