题意:给定n条线段,如果线段之间有相交的,那么他们就会合并成一个新的线段,现在要删除一个线段,使得去掉后联合后的线段最多。
思路:主要还是参考了大佬的解法(https://www.cnblogs.com/Lanly/p/12181097.html),思维很缜密,反正本菜鸟肯定想道这么细的。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+1;
typedef long long ll;
ll cns,ans;
vector<pair<ll,ll>>v;
bool cmp(const pair<ll,ll> &a,const pair<ll,ll> &b)
{
return a.first<b.first||(a.first==b.first&&a.second<b.second);
}
int main()
{
int n,T;
scanf("%d",&T);
while(T--)
{
v.clear();
cns=ans=0;
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
ll l,r;
scanf("%lld %lld",&l,&r);
v.push_back({l,r});
}
sort(v.begin(),v.end(),cmp);
ll one=v[0].second,two=-0x3f3f3f3f,cnt=0;
for(int i=1;i<v.size();++i)
{
if(v[i].first>one)//如果当前线段i的左端点大于前面i-1中最大的右端点时,说明线段此时原本就有空位,同时cnt要清零;
{
++cns;
one=v[i].second;
two=-0x3f3f3f3f;
ans=max(ans,cnt);
cnt=0;
}
else if(two==-0x3f3f3f3f) two=min(one,v[i].second),one=max(one,v[i].second);//更新一下最大值和次大值
else {
if(v[i].first>two) ++cnt;//表示的是只被当前线段覆盖的区间个数
if(v[i].second>=one) ans=max(ans,cnt),cnt=0;
two=max(two,min(one,v[i].second));
one=max(one,v[i].second);
}
}
ans=max(ans,cnt);
if(cns+1==n) {
printf("%lld\n",cns);
continue;
}
printf("%lld\n",ans+cns+1);
}
}