Codeforces 1462F The Treasure of The Segments

題意node

\(n(1\leq n\leq 2*10^5)\)個線段$[l_i,r_i] (1≤l_i≤r_i≤10^9) $,問最少刪除幾個線段,使得剩下線段中,有至少一個線段與全部線段相交。ios

分析c++

對於線段相交且在線段端點數據範圍很大的狀況下,第一想法是離散化。數組

若是枚舉一個線段和其餘全部線段判交,時間複雜度是\(O(n^2)\),顯然是沒法接受的,考慮如何優化。優化

對於一個左端點爲\(l_i\),右端點爲\(r_i\)的線段,咱們能夠考慮,如有另外一個具備相同左端點,右端點爲\(r\),且\(r>r_i\)的線段,取另外一個線段做爲交線段更優。spa

那麼咱們能夠考慮枚舉左端點,以上述最大的\(r\)爲右端點判交,但如果還與其餘全部線段判交,時間複雜度仍然是\(O(n^2)\)指針

再次考慮優化,因爲咱們作法是枚舉左端點\(i\),那麼隨着左端點增大,相交的線段也會變化,咱們考慮這個變化量,將線段排序,這樣能夠保證在右端點增大時,新增線段在數組中是連續的,這樣便可考慮雙指針。code

在以前的所取集合中,大部分線段是仍然能夠與當前線段相交的,而沒法相交的是右端點爲\(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;
}
相關文章
相關標籤/搜索