F. The Treasure of The Segments
难度比
− 908 13614 -\frac{908}{13614} −13614908
题意
给你
n
n
n 条线段,每条位置
[
l
i
,
r
i
]
[l_i,r_i]
[li,ri]
让你删掉最少数量的线段后,剩下的线段集合至少有一个线段
s
s
s,满足该线段与其他线段都相交(交点可以是点也可以是线段)
问你,最少删掉多少条线段?
数据范围
1
≤
n
≤
2
×
1
0
5
1\le n\le 2\times 10^5
1≤n≤2×105
1
≤
l
i
≤
r
i
≤
1
0
9
1\le l_i\le r_i\le 10^9
1≤li≤ri≤109
思路
- 什么情况两条线段是相交的? s i ∩ s j ⟺ max ( l i , l j ) ≤ min ( r i , r j ) s_i\cap s_j\iff \max(l_i,l_j) \le \min(r_i,r_j) si∩sj⟺max(li,lj)≤min(ri,rj)
- 这样不好考虑。我们考虑反面:什么情况两条线段是不相交的? l i > r j ∨ r i < l j l_i > r_j \vee r_i < l_j li>rj∨ri<lj
- 这个情况就比较好考虑了。我们对于某一条线段,计算出有多少条线段的右端点小于 l i l_i li,以及多少条线段的左端点大于 r i r_i ri,然后所有答案取 min \min min即可。
- 计算数量使用
l
o
w
e
r
_
b
o
u
n
d
lower\_bound
lower_bound 即可,注意可能比较难写
(?)注意一些小细节。
核心代码
时间复杂度 O ( n log n ) O(n\log n) O(nlogn)
/*
_ __ __ _ _
| | \ \ / / | | (_)
| |__ _ _ \ V /__ _ _ __ | | ___ _
| '_ \| | | | \ // _` | '_ \| | / _ \ |
| |_) | |_| | | | (_| | | | | |___| __/ |
|_.__/ \__, | \_/\__,_|_| |_\_____/\___|_|
__/ |
|___/
*/
const int MAX = 2e5+50;
struct node{
int lef;
int rig;
}aa[MAX];
vector<int>V1,V2;
int main()
{
int T;scanf("%d",&T);
while(T--){
V1.clear();V2.clear();
int n;scanf("%d",&n);
for(int i = 0;i < n;++i){
scanf("%d%d",&aa[i].lef,&aa[i].rig);
V1.push_back(aa[i].lef);
V2.push_back(aa[i].rig);
}
sort(V1.begin(),V1.end());
sort(V2.begin(),V2.end());
int ans = INF;
for(int i = 0;i < n;++i){
int num1 = lower_bound(V2.begin(),V2.end(),aa[i].lef) - V2.begin();
int num2 = max(0,n - (int)(upper_bound(V1.begin(),V1.end(),aa[i].rig) - V1.begin()));
ans = min(ans,num1 + num2);
}
printf("%d\n",ans);
}
return 0;
}