有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。
单组测试数据。 第一行有两个整数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),表示每一条桥的长度。
如果能够将n座岛连接起来输出YES,否则输出NO。
4 4 1 4 7 8 9 10 12 14 4 5 3 8
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;
}