tutorial
by FHVirus
水題大賽?
Naïve!
三角形、多邊形、凸多邊形、直角、面積
大家都會吧?
以下是不嚴謹的簡單的介紹><
大概可以描述兩個向量的方向有多一致。
運算方式:\(a \cdot b = a_1 \cdot b_1 + a_2 \cdot b_2 \cdots\)
對於兩個平面的向量:
常用在計算例舉之類的。
注意到,在二維平面的叉積常常直接取數值,
是因為叉積為三維的向量,且 \(a \times b\) 會垂直 \(a, b\)(垂直平面),運算時多當成數值回傳。
計算方式:
對於二維的向量而言,
\(a \times b = a_x \cdot b_y - a_y \cdot b_x\),
注意這會帶正負號。
手算的話也可以以 \(a \times b = |a||b| \sin \theta\) 計算。
判斷兩個向量的夾角!
別擔心,這裡沒有 DP 優化。
掃描、DQ一大堆⋯⋯
都不是今天要教的!
上下凸包分開找!
對於所有點按一軸排序,邊掃邊做事!
還記得叉積嗎?
總複雜度 \(O(n \log n)\)!
struct point{
ll x, y;
point(){}
point(ll x, ll y): x(x), y(y){}
// 不會用到加法就不做了
point operator-(point p){
return point(x - p.x, y - p.y);
}
// Dot Product
ll operator*(point p){
return x * p.x + y * p.y;
}
// Cross Product
// 注意運算子優先度!
ll operator^(point p){
return x * p.y - y * p.x;
}
};
// All points, lower convex, upper convex
int n;
point p[N], lc[N], uc[N];
int lcp, ucp;
int32_t main(){ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin >> n;
FOR(i,n){
int a, b; cin >> a >> b;
p[i] = {a, b};
}
sort(p, p + n, [](point a, point b){
return a.x < b.x;
});
FOR(i,n){
while(ucp > 1 and
((p[i] - uc[ucp - 2]) ^ (uc[ucp - 1] - uc[ucp - 2])) >= 0)
--ucp;
while(lcp > 1 and
((p[i] - lc[lcp - 2]) ^ (lc[lcp - 1] - lc[lcp - 2])) <= 0)
--lcp;
uc[ucp++] = p[i];
lc[lcp++] = p[i];
}
// 凸包最左最右會重複算到
cout << ucp + lcp - 2 << '\n';
return 0;
}
動態凸包什麼的之後再說
大家應該都會算吧?
應該也不少人看過這個:
\[ \begin{align} & \frac{1}{2} \begin{vmatrix} x_1 & x_2 & x_3 & \cdots \\ y_1 & y_2 & y_3 & \cdots \end{vmatrix} \\ = & (x_1 \cdot y_2 - y_1 \cdot x_2) + \cdots + (x_n \cdot y_1 - y_n \cdot x_1) \\ = & v_1 \times v_2 + v_2 \times v_3 + \cdots + v_n \times v_1 \end{align} \]
這東西對於所有多邊形都可以用!
按照逆時針排序點,
順時針的話就取個負號,
複雜度 \(O(n)\)!
觀察一下不難發現,
最遠點對一定是凸包上的點對!
怎麼做?
Naïve!
我們沿凸包逆時針進行,
對於遇到的每一個點,
其對應到的最遠點也只會逆時針走!
Naïve!
枚舉每個點當直角,
其他的點按照極角排序好,
雙指針掃過去!
(極角:從 x 軸開始逆時針走的夾角)
還記得內外積嗎?
warner1129
把第三、四象限的點以原點對稱過去!
應該是本課最難搞的東西
給你平面上四個點 \(A, B, C, D\),
求 \(\overline{AB}\) 與 \(\overline{CD}\) 有沒有相交?
想想看?
怎麼判斷一個點在不在簡單多邊形內部?
一個點隨便取一條射線,
若射線交簡單多邊形於奇數個點,
則在多邊形內!
怎麼做?
亂做!
不要中毒!
很重要
不要被 IOI 嚇到啦w
這題不難?
還算簡單吧?
從頭想,觀察一下!
提示:平面距離有分三種。
對於兩個點 \(i, j\),他們的距離:
可以發現,如果題目要求的是切比雪夫的話,就可以用區間資料結構掃過去!
但是,要怎麼做?
展開過程,
如果你上課的時候還看到這邊,
代表 FHVirus
沒做完講義,
她會負責現場導一次的。
這個技巧在二維可以把曼哈頓轉成切比雪夫!
三維也用一樣的技巧,
只不過你的式子會有四個維度!
恭喜你會一題 IOI 囉!