思路
思路還是很顯然的,簡單總結一下思路:
- 首先,將圓環從點 \(1\) 到 \(2N\) 切開,並將其拉直成一條直線。
- 在切開狀態下,原來的弦變成了直線上的曲線。我們需要判斷這些曲線之間是否存在交點。
- 在切開狀態下,曲線之間的交點等價於滿足 \(A_i < A_j < B_i < B_j\) 的不同曲線 \(i\) 和 \(j\) 的存在。
- 為了判斷曲線之間是否存在交點,我們可以使用棧來管理曲線。首先,準備一個空棧 \(S\)。
- 遍歷直線上的每個點,按順序執行以下操作:
- 如果當前點是某個曲線的左端點,將該曲線的識別符號加入棧 \(S\) 的末尾。
- 如果當前點是某個曲線的右端點,從棧 \(S\) 的末尾移除一個元素。
- 如果移除的元素不是當前曲線的識別符號,說明存在交點,返回結果並終止程式。
- 如果程式在遍歷結束後沒有返回結果,說明曲線之間不存在交點。
這種使用棧的演算法能夠在 \(O(N)\) 的時間複雜度內判斷曲線之間是否存在交點。
程式碼
#include<bits/stdc++.h>
using namespace std;
pair<int,int> s[400010];
int stk[400010];
signed main() {
int n;
cin>>n;
for(int i=0;i<n;i++){
int a,b;
cin>>a>>b;
if(a>b) swap(a,b);
s[a-1]={0,i};
s[b-1]={1,i};
}
int p=0;
for(int i=0;i<2*n;i++) {
int t=s[i].first, num=s[i].second;
if(t==0) stk[++p]=num;
else {
if(stk[p]!=num) {
cout<<"Yes";
return 0;
}
p--;
}
}
cout<<"No";
return 0;
}