CF1044A
注意到横着的障碍如果左端点不是 \(1\) 那么是一定不用拆的(要么把挡在它下面的左端点是 \(1\) 的障碍直接拆掉,要么拆掉若干个竖的障碍然后把左端点是 \(1\) 的障碍绕掉,反正拆了也没用,左端点是 \(1\) 的还会挡着)。那么对竖的障碍和有效的横的障碍分别按横坐标排序后,考虑二分答案,判定时如果当前已经能够拆完水平障碍就可以(除去能绕开的),否则花费 \(1\) 次拆掉最靠左的竖的障碍,继续下去即可。
注意 \(l=1,r=10^9\) 的情况,此时直接拆掉即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 500010
#define int long long
using namespace std;
int n,m,a[N],b[N],tot,mid,ans,sum;
bool ck(int x){
for(int i=1,j=1;i<=n;i++){
while(j<=m&&b[j]<a[i])j++;
if(m-j+1<=x)return true;
x--;
}
if(x>=0)return true;
return false;
}
signed main(){
int l,r,h,mid;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
for(int i=1;i<=m;i++){
cin>>l>>r>>h;
if(l==1&&r!=1e9)b[++tot]=r;
else if(l==1&&r==1e9)sum++;
}
m=tot;
sort(b+1,b+m+1);
l=0,r=n+m;
while(l<=r){
mid=(l+r)/2;
if(ck(mid))ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans+sum;
return 0;
}

浙公网安备 33010602011771号