排序 + 二分 - The Treasure of The Segments - CF 690 F
题意:
给 定 n 个 区 间 , 给定n个区间, 给定n个区间,
现 在 从 中 删 除 一 些 区 间 , 使 得 这 n 个 区 间 中 至 少 存 在 一 个 区 间 , 现在从中删除一些区间,使得这n个区间中至少存在一个区间, 现在从中删除一些区间,使得这n个区间中至少存在一个区间,
满 足 这 个 区 间 和 其 他 所 有 的 区 间 都 相 交 。 满足这个区间和其他所有的区间都相交。 满足这个区间和其他所有的区间都相交。
计 算 最 少 删 除 多 少 个 区 间 , 能 够 满 足 条 件 。 计算最少删除多少个区间,能够满足条件。 计算最少删除多少个区间,能够满足条件。
输入:
首 行 一 个 正 整 数 T , 表 示 测 试 数 据 个 数 , 首行一个正整数T,表示测试数据个数, 首行一个正整数T,表示测试数据个数,
每 组 数 据 首 行 一 个 正 整 数 n , 表 示 区 间 数 量 , 每组数据首行一个正整数n,表示区间数量, 每组数据首行一个正整数n,表示区间数量,
接 着 n 行 , 每 行 两 个 正 整 数 , 表 示 区 间 的 左 右 端 点 l i , r i 。 接着n行,每行两个正整数,表示区间的左右端点l_i,r_i。 接着n行,每行两个正整数,表示区间的左右端点li,ri。
输出:
一 个 正 整 数 , 表 示 答 案 。 一个正整数,表示答案。 一个正整数,表示答案。
Example
input
4
3
1 4
2 3
3 6
4
1 2
2 3
3 5
4 5
5
1 2
3 8
4 5
6 7
9 10
5
1 5
2 4
3 5
3 8
4 8
output
0
1
2
0
数据范围:
数 据 保 证 ∑ n ≤ 2 ⋅ 1 0 5 , 1 ≤ l ≤ r ≤ 1 0 9 数据保证\sum n\le 2·10^5,1\le l\le r\le 10^9 数据保证∑n≤2⋅105,1≤l≤r≤109
分析:
最 初 的 想 法 是 : 对 每 个 区 间 , 统 计 和 这 个 区 间 相 交 的 区 间 数 , n − 最 大 值 就 是 答 案 。 最初的想法是:对每个区间,统计和这个区间相交的区间数,n-最大值就是答案。 最初的想法是:对每个区间,统计和这个区间相交的区间数,n−最大值就是答案。
问 题 在 于 , 很 难 在 n l o g n 的 时 间 复 杂 度 内 统 计 出 和 每 个 区 间 相 交 的 区 间 数 。 问题在于,很难在nlogn的时间复杂度内统计出和每个区间相交的区间数。 问题在于,很难在nlogn的时间复杂度内统计出和每个区间相交的区间数。
所 以 , 我 们 反 过 来 思 考 , 对 每 个 区 间 , 统 计 和 该 区 间 不 相 交 的 区 间 数 , 那 么 最 小 值 就 是 答 案 。 所以,我们反过来思考,对每个区间,统计和该区间不相交的区间数,那么最小值就是答案。 所以,我们反过来思考,对每个区间,统计和该区间不相交的区间数,那么最小值就是答案。
而 与 每 个 区 间 不 相 交 的 区 间 数 是 好 统 计 的 , 因 为 , 和 区 间 [ l i , r i ] 和 [ l 0 , r 0 ] 不 相 交 , 只 有 两 种 情 况 : 而与每个区间不相交的区间数是好统计的,因为,和区间[l_i,r_i]和[l_0,r_0]不相交,只有两种情况: 而与每个区间不相交的区间数是好统计的,因为,和区间[li,ri]和[l0,r0]不相交,只有两种情况:
① 、 r 0 < l i ①、r_0<l_i ①、r0<li
② 、 l 0 > r i ②、l_0>r_i ②、l0>ri
首 先 , 我 们 对 区 间 的 左 端 点 和 右 端 点 分 别 排 序 , 首先,我们对区间的左端点和右端点分别排序, 首先,我们对区间的左端点和右端点分别排序,
然 后 , 对 于 每 个 区 间 [ l i , r i ] , 我 们 二 分 第 一 个 > r i 的 左 端 点 的 位 置 p o s 1 , 它 的 贡 献 是 n − p o s 1 + 1 然后,\\ \ \\对于每个区间[l_i,r_i],我们二分第一个>r_i的左端点的位置pos_1,它的贡献是n-pos_1+1 然后, 对于每个区间[li,ri],我们二分第一个>ri的左端点的位置pos1,它的贡献是n−pos1+1
我 们 再 二 分 第 一 个 ≥ l i 的 右 端 点 的 位 置 p o s 2 , 它 的 贡 献 是 p o s 2 − 1 。 我们再二分第一个\ge l_i的右端点的位置pos_2,它的贡献是pos_2-1。 我们再二分第一个≥li的右端点的位置pos2,它的贡献是pos2−1。
最 后 我 们 更 新 最 小 值 m i n 1 ≤ i ≤ n ( n − p o s 1 + 1 , p o s 2 − 1 ) , 即 答 案 。 最后我们更新最小值min_{1\le i\le n}(n-pos_1+1,pos_2-1),即答案。 最后我们更新最小值min1≤i≤n(n−pos1+1,pos2−1),即答案。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#define P pair<int,int>
#define l first
#define r second
using namespace std;
const int N = 200010;
int n, T;
P s1[N], s2[N];
int l[N], r[N];
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
int l, r;
cin>>l>>r;
s1[i]={l,r}, s2[i]={r,l};
}
sort(s1+1,s1+n+1);
sort(s2+1,s2+n+1);
for(int i=1;i<=n;i++)
l[i] = s1[i].l,
r[i] = s2[i].l;
int ans = n;
for(int i=1;i<=n;i++)
{
int tmp = 0;
int pos = upper_bound(l+1,l+n+1,s1[i].r) - l;
tmp += n - pos + 1;
pos = lower_bound(r+1,r+n+1,s1[i].l) - r;
tmp += pos - 1;
ans = min(ans, tmp);
}
cout<<ans<<endl;
}
return 0;
}