D - Segment Tree
题意 : n条线段 当 li<lj<ri<rj 时 i,j之间有一条边相连。问这n条线段能否构成一棵树
思路:
树:无环,任意两点间都有一个公共祖先,最多n-1条边
按左端点排序之后发现li<lj 已经满足了
那么对于第i个线段 只需找到 前面的rj满足 li<rj<ri 即可,因为最多n-1条边,并不会遍历太多次
没想到 n-1这个限制导致没做出来
#include<bits/stdc++.h>
using namespace std;
typedef long long L;
typedef pair<int,int>pii;
const int maxn=5e5+5;
const int oo=1e9+7;
set<pii>::iterator p;
struct node
{
int l,r;
}a[maxn];
int fa[maxn];
bool cmp(node a,node b){if(a.l==b.l)return a.r<b.r;return a.l<b.l;}
int fid(int x){
if(x==fa[x]) return x;
return fa[x]=fid(fa[x]);
}
int main()
{
int n;scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d %d",&a[i].l,&a[i].r),fa[i]=i;
sort(a+1,a+1+n,cmp);
int num=0,f=0;
set<pii>s;
s.insert({a[1].r,1});
for(int i=2;i<=n;i++){
p=s.lower_bound({a[i].l,-1});
for(;p!=s.end();p++){
if(p->first > a[i].r) break;
num++;
if(num>=n) break;
int fp=fid(p->second),fi=fid(i);
if(fp==fi) {f=1;break;}
fa[max(fi,fp)]=min(fi,fp);
}
s.insert({a[i].r,i});
if(num>=n||f) break;
}
if(num>=n||f) {printf("NO\n");return 0;}
set<int>st;
for(int i=1;i<=n;i++){
st.insert(fid(i));
}
printf(st.size()<=1?"YES\n":"NO\n");
}
/* 6 9 12 2 11 1 3 6 10 5 7 4 8 */