zoukankan      html  css  js  c++  java
  • Codeforces 1462F The Treasure of The Segments

    题意

    (n(1leq nleq 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 << '
    ';
    }
    
    signed main() {
        start;
        cin >> T;
        while (T--)
            solve();
        return 0;
    }
    
  • 相关阅读:
    Ubuntu开发环境配置
    win7和Ubuntu16.04之间相互远程控制
    QT学习之usb摄像头采集(Opencv+QT)[cvCapture,IplImage,QImage]
    Opencv 图像畸变矫正(after 相机标定, 获得内参和畸变参数)
    opencv角点检测、棋盘格检测、亚像素cvFindCornerSubPix()
    开始学习机加工钣金加工
    今夜的硬件之旅
    关于做实验
    机器学习部分题目
    ubuntu18.10配置git和github
  • 原文地址:https://www.cnblogs.com/F-Mu/p/14143120.html
Copyright © 2011-2022 走看看