51nod 1460 连接小岛 贪心+multiset的用法

来源:互联网 发布:尚书文字识别软件 编辑:程序博客网 时间:2024/04/29 20:10

有n个小岛,每一个小岛是直线型的,他们不相互相交,第i个小岛所占的区间是[li, ri],而且, ri <  li+1  对于所有的 1 ≤ i ≤ n-1。现在要将相邻的小岛用桥连接起来。现在有一条桥的长度是a,第i个岛和第i+1个岛能够连接的条件是,存在x,y使得 li ≤ x ≤ ri,  li+1  y  ri+1  且 y - x = a成立。

现在有m条桥,每条桥最多被使用一次,问能否把这些岛连接起来。

样例解释:在这个样例中,把第2条桥两个端点放在3和8,把第三条桥两个端点放在7和10,把第一条桥的端点放在10和14。


Input
单组测试数据。第一行有两个整数n (2 ≤ n ≤ 2*10^5) 和 m (1 ≤ m ≤ 2*10^5),表示岛的数目和桥的数目。接下来n行,每行有两个整数 li 和 ri (1 ≤ li ≤ ri ≤ 10^18),表示岛的两个端点。接下来一行有m个整数 a1, a2, ..., am (1 ≤ ai ≤ 10^18),表示每一条桥的长度。
Output
如果能够将n座岛连接起来输出YES,否则输出NO。
Input示例
4 41 47 89 1012 144 5 3 8
Output示例

YES


这里学到了multiset的用法。这个允许存放重复值

P.multiset(a) 返回p数组中比a大的第一个数字所在的位置。

我们就是每次都找比左边界大的尽可能小的数,之后判断一下这个数是否存在(!=end)以及小于右边界。

之后删除。

如果对于某个区间我们找不到这样的数,说明没法建桥,也就没办法连接起来了

#include<iostream>
#include<string.h>
#include<set>
#include<algorithm>
using namespace std;
int n, m;
struct Seg
{
    long long l, r;
    bool operator<(const Seg &P)const {
        if(r == P.r) return l < P.l;
        return r < P.r;
    }
} S[210000];
long long L[210000], R[210000];
multiset<long long>P;


bool solve() {
    int c = 1;
    for(int i = 1; i <= n - 1; i++) {
        multiset<long long>::iterator it = P.lower_bound(S[i].l);
        if(it == P.end() || *it > S[i].r) return false;
        P.erase(it);
    }
    return true;
}
int main() {
    //FIN;
    cin>>n>>m;
    for(int i = 1; i <= n; i++) {
       cin>>L[i]>>R[i];
    }
    for(int i = 1; i <= n - 1; i++) {
        S[i].l = L[i + 1] - R[i] + 1;
        S[i].r = R[i + 1] - L[i] + 1;
    }
    for(int i = 1; i <= m; i++) {
        long long t;
        cin>>t;
         t++;
        P.insert(t);
    }
    sort(S + 1, S + n);
    if(solve())
        cout<<"YES"<<endl;
    else
    {
        cout<<"NO"<<endl;
    }


    return 0;
}