• CF555B Case of Fugitive


    题目大意

      有一些不相交线段和一些桥,桥可以架在两个相邻的线段上。求现有的桥是否可以使所有线段连通。

    题解

      在两个线段上架桥,桥的长度在一个范围内,相当于一个长度的区间,一个桥只有一个长度,相当于一个长度的。这就转化成了点匹配区间问题。

      点匹配区间问题我们在贪心(POJ3614)那里学了,把所有区间按照左端点从大到小排序,把点按照位置从大到小排序,每次总是把最右侧区间与在该区间内的最右端点匹配。问题是:如何满足可以随时删除点,且可以快速找到该区间内的最右端点呢?用key值为点的长度递减的multiset的delete和lower_bound函数可以轻松解决。注意delete时传的参数时迭代器(指针),而不是值,否则一删就把重合的点全删了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <set>
    using namespace std;
    
    const int MAX_LAND = 200010, MAX_BRIDGE = 200010;
    int TotLand, TotLenRange, TotBridge;
    int Ans[MAX_BRIDGE];
    
    struct Bridge
    {
        long long Len;
        int OrgP;
    
        bool operator < (const Bridge& a) const
        {
            return Len > a.Len;
        }
    }_bridges[MAX_BRIDGE];
    
    struct Cmp
    {
        bool operator () (const Bridge& a, const Bridge& b)
        {
            return a.Len < b.Len;
        }
    };
    
    struct Land
    {
        long long L, R;
    
        bool operator < (const Land& a) const
        {
            return L < a.L;
        }
    }_lands[MAX_LAND];
    
    struct LenRange
    {
        long long L, R;
        int OrgL;
    
        bool operator < (const LenRange& a) const
        {
            return L > a.L;
        }
    }_lenRanges[MAX_LAND];
    
    void Read()
    {
        scanf("%d%d", &TotLand, &TotBridge);
        TotLenRange = TotLand - 1;
        for (int i = 1; i <= TotLand; i++)
            scanf("%lld%lld", &_lands[i].L, &_lands[i].R);
        for (int i = 1; i <= TotBridge; i++)
            scanf("%lld", &_bridges[i].Len);
    }
    
    void Init()
    {
        for (int i = 1; i <= TotBridge; i++)
            _bridges[i].OrgP = i;
        sort(_lands + 1, _lands + TotLand + 1);
        for (int i = 1; i <= TotLand - 1; i++)
        {
            _lenRanges[i].L = _lands[i + 1].L - _lands[i].R;
            _lenRanges[i].R = _lands[i + 1].R - _lands[i].L;
            _lenRanges[i].OrgL = i;
        }
        sort(_lenRanges + 1, _lenRanges + TotLenRange + 1);
    }
    
    void Solve()
    {
        static multiset<Bridge> tree;
        for (int i = 1; i <= TotBridge; i++)
            tree.insert(_bridges[i]);
        for (int i = 1; i <= TotLenRange; i++)
        {
            Bridge temp;
            temp.Len = _lenRanges[i].R;
            multiset<Bridge>::iterator it = tree.lower_bound(temp);
            if (it == tree.end() || it->Len <_lenRanges[i].L )
            {
                printf("No
    ");
                return;
            }
            Ans[_lenRanges[i].OrgL] = it->OrgP;
            tree.erase(it);
        }
        printf("Yes
    ");
        for (int i = 1; i <= TotLand - 1; i++)
            printf("%d ", Ans[i]);
        printf("
    ");
    }
    
    int main()
    {
        Read();
        Init();
        Solve();
        return 0;
    }
    

      

  • 相关阅读:
    npm总是安装不成功,而且很慢?
    Nginx启动报错:10013: An attempt was made to access a socket in a way forbidden
    firebug如何使用
    video详解 HTML5中的视频:
    树的各种遍历
    SQL语句执行顺序
    vim常用命令
    无监督分类算法—K-Means
    Json字符串和Json对象的简单总结
    List拆分成多个集合
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9427071.html
Copyright © 2020-2023  润新知