zoukankan      html  css  js  c++  java
  • cf555b

    题意:按顺序给出多个互不相交的区间(表示一些小岛),和一些可以连接区间的桥,每个桥有固定的长度。区间和桥的数量都是2*10^5。

    两个相邻的小岛之间的桥的长度必须小于等于最远点距离,大于等于最近点距离。问是否能用这些桥把所有小岛连接在一起。

    分析:区间排序问题。但是这个题里需要排序的区间并不是题里直接给出的小岛。而是要先把桥从小到大排序。

    然后对于每两个相邻小岛,在这个桥的序列里都有一个区间内的桥是可以用来连接这两个小岛的。

    对于每两个相邻小岛,求出其对应的桥区间,然后把这些区间排序。

    排序规则是先按右边缘从小到大,右边相同的按左边缘从小到大。

    排序后依次在这些区间里选取对应的桥,每次选取区间内最小的未被使用的桥即可。

    至于排序的时候为什么先又后左,是因为不同区间对于左侧的桥资源的迫切程度,肯定是右边缘越偏左,需求越迫切。

    所以应当优先将左侧的资源分配给右边缘比较偏左的区间。

    要求一个数字集合里面位于一个区间内的最小值,可以用lower_bound函数。

    而依次删除使用过的桥,可以用multiset(它有lower_bound这个成员函数)。

    当想要使用包含三个值的结构体的时候,可以用两个pair嵌套。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    using namespace std;
    
    #define d(x) 
    
    const int MAX_N = 2 * (int)(1e5) + 10;
    
    pair<long long, long long> island[MAX_N];
    int bridge_num;
    int island_num;
    int ans[MAX_N];
    pair<long long, pair<long long, int> > range[MAX_N];
    multiset<pair<long long, int> > bridge;
    
    bool ok()
    {
        for (int i = 0; i < island_num - 1; i++)
        {
            long long l = range[i].second.first;
            long long r = range[i].first;
            __typeof(bridge.begin()) it = bridge.lower_bound(make_pair(l, -1));
            if (it == bridge.end())
                return false;
            if ((*it).first > r)
                return false;
            ans[range[i].second.second] = it->second;
            bridge.erase(it);
        }
        return true;
    }
    
    void input()
    {
        scanf("%d%d", &island_num, &bridge_num);
        for (int i = 0; i < island_num; i++)
        {
            long long a, b;
            cin >> a >> b;
            island[i] = make_pair(a, b);
        }
        for (int i = 0; i < bridge_num; i++)
        {
            long long a;
            cin >> a;
            bridge.insert(make_pair(a, i));
        }
    }
    
    int main()
    {
        input();
    
        for (int i = 0; i < island_num - 1; i++)
        {
            long long min_len = island[i + 1].first - island[i].second;
            long long max_len = island[i + 1].second - island[i].first;
            range[i] = make_pair(max_len, make_pair(min_len, i));
        }
    
        sort(range, range + island_num - 1);
    
        if (ok())
        {
            puts("Yes");
            for (int i = 0; i < island_num - 1; i++)
            {
                if (i != 0)
                    putchar(' ');
                printf("%d", ans[i] + 1);
            }
            putchar('
    ');
        }
        else
            puts("No");
        return 0;
    }
    View Code
  • 相关阅读:
    删除表空间的时候遇到的问题:ORA-02429: 无法删除用于强制唯一/主键的索引
    删除
    Activity中使用getSystemService获得系统服务
    用多线程实现反应灵敏的界面(Java)
    用数组实现3个栈之固定分割(Java)
    Android小知识点20条
    Android数据库中数据文件的导出与查看
    MFC中使用CSplitterWnd分割窗口后设置视图大小的问题
    MFC中,通过preCreateWindow函数无法设置视图样式(包括窗口的大小)
    6:Node.js 路由
  • 原文地址:https://www.cnblogs.com/rainydays/p/4646926.html
Copyright © 2011-2022 走看看