Codeforces 1462F The Treasure of The Segments
阅读原文时间:2023年09月03日阅读:1

题意

给\(n(1\leq n\leq 2*10^5)\)个线段$[l_i,r_i] (1≤l_i≤r_i≤10^9) $,问最少删除几个线段,使得剩下线段中,有至少一个线段与所有线段相交。

分析

对于线段相交且在线段端点数据范围很大的情况下,第一想法是离散化。

如果枚举一个线段和其他所有线段判交,时间复杂度是\(O(n^2)\),显然是无法接受的,考虑如何优化。

对于一个左端点为\(l_i\),右端点为\(r_i\)的线段,我们可以考虑,若有另一个具有相同左端点,右端点为\(r\),且\(r>r_i\)的线段,取另一个线段作为交线段更优。

那么我们可以考虑枚举左端点,以上述最大的\(r\)为右端点判交,但若是还与其他所有线段判交,时间复杂度仍然是\(O(n^2)\)。

再次考虑优化,由于我们做法是枚举左端点\(i\),那么随着左端点增大,相交的线段也会变化,我们考虑这个变化量,将线段排序,这样可以保证在右端点增大时,新增线段在数组中是连续的,这样即可考虑双指针。

在之前的所取集合中,大部分线段是仍然可以与当前线段相交的,而无法相交的是右端点为\(i-1\)的线段,所以当一条线段加入集合中,在其\(r_i\)上做一个标记,遍历到时减去数字即可。

#pragma GCC optimize(3, "Ofast", "inline")

#include <bits/stdc++.h>

#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define ull unsigned long long
#define int ll
#define ls st<<1
#define rs st<<1|1
#define pii pair<int,int>
#define rep(z, x, y) for(int z=x;z<=y;++z)
#define repd(z, x, y) for(int z=x;z>=y;--z)
#define com bool operator<(const node &b)const
using namespace std;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
const int maxn = (ll) 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int T = 1;
int sum[maxn];
pii a[maxn];
int r[maxn];

void solve() {
    int n;
    cin >> n;
    vector<int> v;
    rep(i, 1, n) {
        cin >> a[i].first >> a[i].second;
        v.push_back(a[i].first);
        v.push_back(a[i].second);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    rep(i, 0, v.size())r[i] = sum[i] = 0;
    rep(i, 1, n) {
        a[i].first = lower_bound(v.begin(), v.end(), a[i].first) - v.begin() + 1;
        a[i].second = lower_bound(v.begin(), v.end(), a[i].second) - v.begin() + 1;
        r[a[i].first] = max(r[a[i].first], a[i].second);
    }
    sort(a + 1, a + n + 1);
    int now = 0;
    int ans = 1;
    int pos = 1;
    rep(i, 0, v.size()) {
        now -= sum[i - 1];
        while (pos <= n) {
            if (a[pos].first <= r[i]) {
                ++sum[a[pos].second];
                ++pos;
                ++now;
            } else
                break;
        }
        ans = max(ans, now);
    }
    cout << n - ans << '\n';
}

signed main() {
    start;
    cin >> T;
    while (T--)
        solve();
    return 0;
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器