[ABC338E] Chords 題解

merlinkkk發表於2024-07-16

思路

思路還是很顯然的,簡單總結一下思路:

  1. 首先,將圓環從點 \(1\)\(2N\) 切開,並將其拉直成一條直線。
  2. 在切開狀態下,原來的弦變成了直線上的曲線。我們需要判斷這些曲線之間是否存在交點。
  3. 在切開狀態下,曲線之間的交點等價於滿足 \(A_i < A_j < B_i < B_j\) 的不同曲線 \(i\)\(j\) 的存在。
  4. 為了判斷曲線之間是否存在交點,我們可以使用棧來管理曲線。首先,準備一個空棧 \(S\)
  5. 遍歷直線上的每個點,按順序執行以下操作:
    • 如果當前點是某個曲線的左端點,將該曲線的識別符號加入棧 \(S\) 的末尾。
    • 如果當前點是某個曲線的右端點,從棧 \(S\) 的末尾移除一個元素。
    • 如果移除的元素不是當前曲線的識別符號,說明存在交點,返回結果並終止程式。
  6. 如果程式在遍歷結束後沒有返回結果,說明曲線之間不存在交點。

這種使用棧的演算法能夠在 \(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;
}