CodeForces 1454 F. The Treasure of The Segments
题目大意:
给定一个有 n n n 个线段的集合,假设集合中有一个线段与其他所有线段有交点,则表示这个集合是好的,问最少删除几个线段可以让集合变好.
思路:
第一种想法:枚举每个线段 x x x,看看有几个线段和这个线段相交,没有交点的线段自然就删去,记录一个最小值,这种做法就要对按某个端点线段排序,对有序的端点使用二分查找,但对无序的另一端就要使用某些数据结构比如 B I T BIT BIT 主席树这种。这种写起来就不方便
第二种想法:枚举每个线段 x x x,找哪些线段和这个线段没有交点,这种反过来的思考,就会发现处理比第一种简单不少,因为线段不相交情况只有两种:
- i i i 左端点大于 x x x 右端点
- i i i 右端点小于 x x x 左端点
这样对左右端点分别排序,二分查找即可快速算出不相交的线段数。
代码
#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'
typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;
int li[maxn], ri[maxn];
void solve()
{
int n;
cin >> n;
vector<pii> a(n);
int i = 0;
for(pii& p : a) {
cin >> p.first >> p.second;
li[i] = p.first;
ri[i] = p.second;
++i;
}
sort(li, li+n);
sort(ri, ri+n);
int ans = n;
for(const pii& p : a) {
int d = upper_bound(ri, ri+n, p.first-1)- ri + n - (upper_bound(li, li+n, p.second) - li);
ans = min(ans, d);
}
cout << ans << endl;
}
int main()
{
IOS();
int T;
cin >> T;
while(T--)
solve();
return 0;
}
总结:
最近二分的题好多啊