Segment Tree - Educational Codeforces Round 78 div2 d
#set #sweep line #dsu(disjoint set union) #区間 #segment
解法
intersectの条件
2つの線分の一部が被ってる
(一方が他方を完全に覆っていてはいけない)
一部が被ってる2線分を考える
始点が先の線分を x , 始点が後ろの線分を y とする
x の始点より後に y の始点があり,
xの終点より後に y の終点がある
また, y の始点は x の始点, 終点に挟まれてる
前から見て, x の始点が来たら x の終点をsetに入れる
x の終点が来て x の終点をsetから取り出す前に y の始点が来るか
そして, y の終点は x の終点の後でないといけない
コード
unionfind ver
https://codeforces.com/contest/1278/submission/67319721
int n; cin >> n; vector<pii> a(n); rep(i, n) cin >> a[i].F >> a[i].S; vector<pii> evs; rep(i, n) { evs.eb(pii(a[i].F, i)); evs.eb(pii(a[i].S, i)); // setから取り出すために必要 } sort(all(evs)); int cnt = 0; set<pii> cur; UnionFind uni(n); for (auto it : evs) { // すべての線分の始点を見る if (cnt >= n) break; // curに入ってるのは終点 // この点が終点なら取り出し, とばす // 以降, この線分が見られることはない if (cur.count(it)) { cur.erase(it); } else { int i = it.S; int r = a[i].S; // その線分の終点 for (auto jt : cur) { // 完全に覆われていてはいけない if (jt.F > r) break; int j = jt.S; uni.connect(i, j); cnt++; if (cnt >= n) { cout << "NO" << endl; return 0; } } cur.insert(pii(a[i].S, i)); // 終点を入れる } } cout << (uni.size() == 1 ? "YES" : "NO") << endl;