zoukankan      html  css  js  c++  java
  • [CF1278D] Segment Tree

    [CF1278D] Segment Tree - 扫描线,并查集,set

    Description

    给定 n 条线段,每个线段包括起始坐标,如果两条线段严格相交(非相连),则两条线段间有一条边,问能否构成一颗树。

    Solution

    很容易想到按左端点排序,因为对于线段 a,b,如果 a.l < b.l,则 a,b 相交当且仅当 b.l < a.r < b.r

    判断树的问题,很容易想到并查集

    我们将所有线段按左端点排序后扫描一遍,维护一个 set,每次扫描到线段 i 时,先检查满足 r 在 i.l 和 i.r 之间的线段是否存在,如果能找到,就在并查集中合并,然后再将 i 加入 set 中,因此这个 set 是按线段的 r 排序的

    成树的充要条件是:在合并过程中,没有出现重复合并的情况,并且整个流程执行完后,所有的元素都在同一个集合中

    
    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    struct Segment
    {
        int l, r, id;
        friend bool operator<(const Segment &lhs, const Segment &rhs)
        {
            return lhs.r < rhs.r;
        };
    };
    
    bool cmp(const Segment &lhs, const Segment &rhs)
    {
        return lhs.l < rhs.l;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        int n;
        cin >> n;
    
        vector<Segment> seg(n + 2);
        for (int i = 1; i <= n; i++)
        {
            cin >> seg[i].l >> seg[i].r;
            seg[i].id = i;
        }
        sort(&seg[1], &seg[n + 1], cmp);
    
        vector<int> fa(n + 2);
    
        for (int i = 1; i <= n; i++)
            fa[i] = i;
    
        function<int(int)> find = [&](int x) -> int {
            return x == fa[x] ? x : fa[x] = find(fa[x]);
        };
    
        // 我们将所有线段按左端点排序后扫描一遍,
        // 维护一个 set,每次扫描到线段 i 时,先检查满足 r 在 i.l 和 i.r 之间的线段是否存在,
        // 如果能找到,就在并查集中合并,然后再将 i 加入 set 中,因此这个 set 是按线段的 r 排序的
    
        set<Segment> s;
    
        for (int i = 1; i <= n; i++)
        {
            auto [ql, qr, id] = seg[i];
            auto fir = s.upper_bound({0, ql, 0});
            auto las = s.lower_bound({0, qr, 0});
    
            for (auto it = fir; it != las; it++)
            {
                int x = id, y = it->id;
                x = find(x);
                y = find(y);
                if (x != y)
                    fa[x] = y;
                else
                {
                    cout << "NO" << endl;
                    return 0;
                }
            }
    
            s.insert(seg[i]);
        }
    
        for (int i = 1; i < n; i++)
            if (find(i) != find(n))
            {
                cout << "NO" << endl;
                return 0;
            }
        cout << "YES" << endl;
    }
    
    
  • 相关阅读:
    java基础 IO流
    删除API
    Get API
    Document APIs
    使用Java High Level REST Client操作elasticsearch
    Azure 上的物联网产品介绍
    SSIS Passing Parameters to an ADO .NET Source query;向ado.net数据源传递参数。
    Azure API Management(5)缓存
    Azure API Management(6)Validate JWT Token
    Azure API Management(4)体验APIM 版本管理
  • 原文地址:https://www.cnblogs.com/mollnn/p/14352520.html
Copyright © 2011-2022 走看看