题意:在坐标轴上给定n个线段,用li,ri表示左右端点,问最少删去多少个线段,才能使得剩余线段中,存在一个线段与其余线段都有交集。
分析:题目可以等价为对于每个线段求出和它没有交集的线段个数,然后取最小值就是答案。
那么对于某个线段如何求与他没有交集的线段个数呢?
线段A与线段B没有交集等价为 A的右端点在B的左端点左边,
或者 A的左端点在B的右端点的右边
所以我们可以把左/右端点拿出来存进2个数组里面排好序,
枚举每个线段再利用二分查找就可以解决了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 2e5+5;
const int mx = 40;
const int mod = 1e9+5;
const ll inf = 34359738370;
const int INF = 1e9+7;
int n;
//至少删去多少线段 才能使得剩下的线段中存在一个线段与其余线段有交集
//转化成枚举每个线段x 求出和它不相交的线段个数 取min就是答案
//情况1:右端点在它左端点的左边 直接二分 lower_bound(r+1,r+n+1,x.first)-r-1 (相当于r数组中,值小于x.first的个数)
//情况2:左端点在它右端点的右边 n - (lower_bound(l+1,l+n+1,x.second+1)-l-1)(相当于l数组中,值小于等于x.second的个数)
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
pii seg[n+1];
int l[n+1],r[n+1];
l[0]=0,r[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d %d",&seg[i].first,&seg[i].second);
l[i]=seg[i].first,r[i]=seg[i].second;
}
sort(l+1,l+n+1);
sort(r+1,r+n+1);
int ans=n;
for(int i=1;i<=n;i++)
{
pii x=seg[i];
int v=lower_bound(l+1,l+n+1,x.second+1)-l-1;//左端点在x的右端点以及其左边的线段个数
int d=lower_bound(r+1,r+n+1,x.first)-r-1 + n-v;//n-v就是左端点在右边的个数了
ans=min(ans,d);
}
printf("%d\n",ans);
}
return 0;
}