链接
二分+差分
二分最大值,check得到满足两个条件的解。(以前做的都是满足一种条件的二分,注意体会区别)
题目目的:让共同区间尽可能的长,并且共同区间数目尽可能的多。
我们每次二分得到mid,既指人数,也指长度。
然后第一个for循环记录长度满足≥mid的前缀和人数,第二个for循环差分得到符合≥mid的长度的人数,如果人数sum[i]≥mid,return true,(说明满足两个条件)。
#include<iostream>
#include<cstring>
using namespace std;
const int N=3e5+1000;
typedef pair<int,int> PII;
PII a[N];
int n,m,sum[N];
//二分最大化可行答案,对于每次mid,差分维护判断是否存在连续长度不小于mid且人数也不小于mid的区间
bool check(int mid) //人数≥mid,长度≥mid
{
memset(sum,0,sizeof sum);
for(int i=0;i<m;i++)
{
int len=a[i].second-a[i].first+1;
if(len>=mid) //第一个条件
{
sum[a[i].first+mid-1]++;
sum[a[i].second+1]--;
}
}
for(int i=1;i<=n;i++)
{
sum[i]+=sum[i-1];
if(sum[i]>=mid) //第二个条件
return true;
}
return false;
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++) cin>>a[i].first>>a[i].second;
int l=0,r=m-1;
while(l<r)
{
int mid=(l+r+1)/2;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<endl;
return 0;
}