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

题意
给了n个区间,对于任意两个区间,如果两个区间有交集,那么就对这两个区间连边。(要求区间不能是对方的子集)。问进行连边之后,能不能形成一棵树。

思路
考虑暴力建边的话,n^2的复杂度显然是不允许的。
考虑一下,形成一棵树,也就是只需要n-1条边,如果>n-1条边,那么就形成了环了,也就不是树了。
所以我们考虑对输入的区间,进行左端点从小到大排序。
用一个set维护前面的区间的右端点和id。

对于当前的区间,我们是按照左端点排序的,也就是当前左端点L2一定大于set中的左端点L1,那么也就是要找到set中的右端点R1大于当前的左端点L2,并且set中的右端点R1小于当前区间的右端点R2,不然当前的区间就是set中那个区间的子集了。用并查集维护联通的区间的个数即可。
如果形成了环,或者边不足n-1 那么就是NO。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int f[N];
int find(int x){
    return f[x]==x?f[x]:f[x]=find(f[x]);
}
struct node{
    int l,r;
}a[N];
struct E{
    int id,r;
    friend bool operator<(E a,E b){
        return a.r<b.r;
    }
};
set<E> s;
int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i].l,&a[i].r),f[i]=i;
    sort(a+1,a+n+1,[](node a,node b){
         return a.l<b.l;
    });
    int F;
    for(int i=1;i<=n;i++){
        auto it=s.lower_bound({i,a[i].l});
        while(it!=s.end() && it->r < a[i].r){
            int fx=find(it->id),fy=find(i);
            if(fx==fy) goto now;
            f[fx]=fy;
            it++;
        }
        s.insert({i,a[i].r});
    }
    F=find(1);
    for(int i=1;i<=n;i++){
        if(find(i)!=F) goto now;
    }
    puts("YES");
    return 0;
    now: puts("NO");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不会c语言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值