先将数据离散化,然后用线段树统计所有线段叠加起来覆盖最多次数的线段和长度
再单独将每个线段去掉,查询是否有覆盖n-1次的线段,记录最大的长度就可以了
当线段是一个点是要注意特判
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
typedef long long ll;
const int maxn=610000+10;
int lazy[maxn<<2];
int sum[maxn<<2];
int len[maxn<<2];
void PushUp(int rt)
{
if(sum[rt<<1]>sum[rt<<1|1])
{
len[rt]=len[rt<<1];
sum[rt]=sum[rt<<1];
}
else if(sum[rt<<1]<sum[rt<<1|1])
{
len[rt]=len[rt<<1|1];
sum[rt]=sum[rt<<1|1];
}
else
{
len[rt]=len[rt<<1]+len[rt<<1|1];
sum[rt]=sum[rt<<1];
}
}
void PushDown(int rt)
{
if(lazy[rt])
{
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
sum[rt<<1]+=lazy[rt];
sum[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
int a[maxn],cnt;
void build(int l,int r,int rt)
{
lazy[rt]=0;
if(l==r)
{
sum[rt]=0;
len[rt]=a[r]-a[l-1];
return;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
lazy[rt]+=c;
sum[rt]+=c;
return;
}
PushDown(rt);
int m=(l+r)>>1;
if(L<=m) update(L,R,c,l,m,rt<<1);
if(m<R) update(L,R,c,m+1,r,rt<<1|1);
PushUp(rt);
}
int n;
int l[310000],r[310000];
int main()
{
cnt=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&l[i],&r[i]);
a[cnt++]=l[i];a[cnt++]=r[i];
}
sort(a,a+cnt);
int t=1;
for(int i=1;i<cnt;i++)
if(a[i]!=a[i-1]) a[t++]=a[i];
cnt=t;
if(cnt==1)
{
printf("0\n");
return 0;
}
build(1,cnt-1,1);
for(int i=0;i<n;i++)
{
if(l[i]==r[i]) continue;
int lp=lower_bound(a,a+cnt,l[i])-a;
int rp=lower_bound(a,a+cnt,r[i])-a;
update(lp+1,rp,1,1,cnt-1,1);
}
int ans=0;
for(int i=0;i<n;i++)
{
if(l[i]==r[i])
{
if(sum[1]==n-1)
ans=max(ans,len[1]);
continue;
}
int lp=lower_bound(a,a+cnt,l[i])-a;
int rp=lower_bound(a,a+cnt,r[i])-a;
update(lp+1,rp,-1,1,cnt-1,1);
if(sum[1]==n-1)
ans=max(ans,len[1]);
update(lp+1,rp,1,1,cnt-1,1);
}
printf("%d\n",ans);
return 0;
}