https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1460
将两岛之间桥的距离范围拿出来 就是n-1条线段 m座桥看作点 看是否每条线段都能分到至少一个点
这种贪心就是先考虑条件最严苛的 如果从小往大扫的话 显然右端点越小条件越严苛 因为终止时间越早 右端点相同就是左端点大的更严苛 线段树维护一下m个点即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
struct node
{
ll l;
ll r;
};
node seg[maxn];
int sum[4*maxn];
ll lef[maxn],rgt[maxn],ary[maxn],tmp[maxn];
int n,m,len;
bool cmp(node n1,node n2)
{
if(n1.r==n2.r) return n1.l>n2.l;
else return n1.r<n2.r;
}
void update(int tar,int val,int l,int r,int cur)
{
int m;
sum[cur]+=val;
if(l==r) return;
m=(l+r)/2;
if(tar<=m) update(tar,val,l,m,2*cur);
else update(tar,val,m+1,r,2*cur+1);
}
void query(int pl,int pr,int &p,int l,int r,int cur)
{
int m;
if(pl<=l&&r<=pr)
{
if(sum[cur]==0) return;
if(l==r) p=l;
else
{
m=(l+r)/2;
if(sum[2*cur]>0) query(pl,pr,p,l,m,2*cur);
else query(pl,pr,p,m+1,r,2*cur+1);
}
return;
}
m=(l+r)/2;
if(pl<=m&&p==-1) query(pl,pr,p,l,m,2*cur);
if(pr>m&&p==-1) query(pl,pr,p,m+1,r,2*cur+1);
}
int main()
{
int i,p,l,r;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) scanf("%lld%lld",&lef[i],&rgt[i]);
for(i=1;i<=m;i++)
{
scanf("%lld",&ary[i]);
tmp[i]=ary[i];
}
for(i=1;i+1<=n;i++) seg[i].l=lef[i+1]-rgt[i],seg[i].r=rgt[i+1]-lef[i];
sort(seg+1,seg+n,cmp);
sort(tmp+1,tmp+m+1);
len=unique(tmp+1,tmp+m+1)-tmp-1;
for(i=1;i<=m;i++)
{
p=lower_bound(tmp+1,tmp+len+1,ary[i])-tmp;
update(p,1,1,len,1);
}
for(i=1;i<=n-1;i++)
{
l=lower_bound(tmp+1,tmp+len+1,seg[i].l)-tmp;
r=upper_bound(tmp+1,tmp+len+1,seg[i].r)-tmp-1;
if(l<=r)
{
p=-1;
query(l,r,p,1,len,1);
if(p==-1) break;
update(p,-1,1,len,1);
}
else break;
}
if(i==n) printf("YES\n");
else printf("NO\n");
return 0;
}