树状数组维护区间个数
二分找区间长度x
因为找的区间长度满足单调性
如果当前的区间长度x满足题意呢比他小的区间长度也同样满足题意
比他大的不一定
我们现将他们的按len排序
然后每次用他的右端点然后求len-x+1前面的左端点的个数就知道他的区间个数
注意每次枚举完后要将已经枚举过的区间的左端点从树状数组中删去,因为我们枚举的右端点含义是选中的一些区间中最靠左的右端点,然后如果存在一个右端点使得在交集左边的左端点大于x,那么他就满足题意
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
struct road
{
int l,r;
int len;
bool operator < (const road &A)
{
return r<A.r;
}
}a[N],tmp[N];
int ans[N];int n,m;
int lowbit(int x)
{
return x&(-x);
}
int query(int x)
{
int res=0;
while(x)
{
res+=ans[x];
x-=lowbit(x);
}
return res;
}
void add(int x,int pos)
{
while(x<=n)
{
ans[x]+=pos;
x+=lowbit(x);
}
}
bool check(int x)
{
int cnt=0;
for(int i=1;i<=m;i++)
{
if(a[i].len>=x)
{
tmp[++cnt]=a[i];
add(a[i].l,1);
}
}
for(int i=1;i<=cnt;i++)
{
int w=query(tmp[i].r-x+1);
if(w>=x)
{
return true;
}
add(tmp[i].l,-1);
}
return false;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a[i].l>>a[i].r;
a[i].len=a[i].r-a[i].l+1;
}
sort(a+1,a+1+m);
int l=1,r=n;
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid))
{
l=mid+1;
}
else{
r=mid-1;
}
}
cout<<r-1<<endl;
}