Educational Codeforces Round 78 (Rated for Div. 2)D - Segment Tree

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
*/

发布了61 篇原创文章 · 获赞 7 · 访问量 3195

猜你喜欢

转载自blog.csdn.net/qq_43914084/article/details/103668989