給定 N 個點(N ≤ 10^5),判斷能否將它們連成一個所有內角為 90°/270° 的簡單多邊形(即邊平行坐標軸,無自相交,無三點共線),若能則輸出周長,否則輸出 -1。
(x, y1, y2),累加長度 y2-y1,並查集合併兩端點。(y, x1, x2),累加長度,並查集合併。(y, x1, x2) 時:
x < y 的垂直邊按 y1 入優先隊列(小頂堆按 y2)。y2 <= y 的垂直邊(已掃過)。x1 < x < x2 → 相交 → -1。// 垂直邊結構
struct Seg { int x, y1, y2, t; }; // t: 0=垂直, 1=水平
// 掃描水平邊
sort(vert, vert+m, cmpX); // 按 x
sort(horiz, horiz+n, cmpY); // 按 y
priority_queue pq; // 存活垂直邊,按 y2
ListNode *head = new ListNode(0); // 鏈表頭,同步 pq 內容
for (each horiz edge h) {
// 入隊:vert[v].x < h.y
while (v < m && vert[v].x < h.y) {
pq.push(vert[v]);
insertList(head, vert[v].t); // t 為垂直邊 x 坐標
v++;
}
// 出隊:pq.top().y2 <= h.y
while (!pq.empty() && pq.top().y2 <= h.y) {
deleteList(head, pq.top().t);
pq.pop();
}
// 檢查相交:遍歷鏈表,若節點 x 在 (h.x1, h.x2) 內 → 相交
for (node = head->next; node; node = node->next)
if (node->t > h.x1 && node->t < h.x2) return -1;
}
// 最後檢查並查集連通數
if (components > 1) return -1;
return total_perimeter;
本題綜合考察幾何性質推導、並查集連通性、掃描線相交檢測、優先隊列與鏈表協同優化。關鍵在於識別「同坐標兩兩配對」的必然性,並用掃描線高效檢測軸平行線段相交。代碼中鏈表優化優先隊列刪除是工程實現的亮點。