D. Segment Tree
题意
给出n个区间的两端的端点(当作点p),当且仅当两条线段相交认为这两个点相连(无向的),问这是不是一颗树
思路
区间交的处理嘛,一般都是set,怎么判断是否相交呢,而且不判漏呢?我们想到了排序,如果左端点是递增的话,我们就只用看加入的该点跟之前加入的右端点比较就行了(因为有序,只有一种情况)
怎么判断是否是一颗树呢?首先边数为n-1,其次不能有环,所以要判环(并查集就可以了)
code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=5e5+5;
struct segment
{
int l,r;
segment(){}
segment(int l,int r):l(l),r(r){}
bool operator <(const segment &T)const
{
if(l!=T.l)return l<T.l;
return r<T.r;
}
};
set<segment> q;
segment temp[maxn];
int fa[maxn];
int Find(int x)//并查集
{
if(fa[x]==x)return x;
else return Find(fa[x]);
}
int main()
{
int n,cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;++i)fa[i]=i;
for(int i=1;i<=n;++i)scanf("%d%d",&temp[i].l,&temp[i].r);
sort(temp+1,temp+n+1);
for(int i=1;i<=n;++i)
{
while(!q.empty()&&temp[i].l>q.begin()->l)q.erase(q.begin());//将无用的去除
for(auto &it:q)
{
if(it.l>temp[i].r)break;//相离了
int f1=Find(it.r),f2=Find(i);
if(f1==f2){cout<<"NO";return 0;}//同是一个fa,有环
fa[f1]=f2;
cnt++;
}
q.insert(segment(temp[i].r,i));//放右端点跟该点的编号
}
printf("%s\n",cnt==n-1?"YES":"NO");
return 0;
}