区间有关问题

求最长重叠区间

\(n\)个区间,求任意两个区间最长的重叠部分。

解法

首先把所有区间按左端点从小到大排序。设\(mx\)是前若干个区间的右端点最大能达到的值,对于每一个区间,设它的左端点为\(l\),右端点为\(r\),则其它区间与它的最大重叠部分为\(min(mx, r)-l\),遍历每个区间,维护答案。

代码

#include<bits/stdc++.h>

using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;

    vector<array<int, 2>> seg(n);
    for(int i = 0; i < n; i++) {
    	cin >> seg[i][0] >> seg[i][1];
    }
    
    sort(seg.begin(), seg.end());

    int ans = 0, mx = seg[0][1];
    for(int i = 1; i < n; i++) {
    	ans = max(ans, min(mx, seg[i][1]) - seg[i][0] + 1);
    	mx = max(mx, seg[i][1]);
    }

    cout << ans << "\n";

    return 0;
}

合并区间

\(n\)个区间,把相互交叉的区间合并成一个区间。

解法

把所有区间按左端点从大到小排序,然后枚举每一个区间,如果所枚举区间的左端点大于合并区间的右端点,则新增一个合并区间,否则更新维护前合并区间右端的最大值。

代码

#include<bits/stdc++.h>

using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;

    vector<array<int, 2>> seg(n);
    for(int i = 0; i < n; i++) {
        cin >> seg[i][0] >> seg[i][1];
    }
    
    sort(seg.begin(), seg.end());

    vector<array<int, 2>> ans;
    for(int i = 0; i < n; i++) {
        if(!ans.empty() && ans.back()[1] >= seg[i][0]) {
            ans.back()[1] = max(ans.back()[1], seg[i][1]);
        } else {
            ans.push_back({seg[i][0], seg[i][1]});
        }
    }

    for(auto [x, y] : ans) {
        cout << x << " " << y << "\n";
    }

    return 0;
}

求最多的重叠区间数

给定\(n\)个区间,求最多的相符重叠区间的数量。

解法

把每个区间的左右端点存入一个数组中,并标记存入的端点为左端点还是右端点。然后把所有端点从小到大排序,再遍历端点。如果是左端点就令\(cnt\)加1,表示新增了一个区间,否则减1,表示减少了一个区间。\(cnt\)的最大值就是答案。

代码

#include<bits/stdc++.h>

using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;

    vector<array<int, 2>> seg;
    for(int i = 0; i < n; i++) {
        int l, r;
        cin >> l >> r;
        seg.push_back({l, 0});
        seg.push_back({r, 1});
    }

    sort(seg.begin(), seg.end(), [&](array<int, 2> &a, array<int, 2> &b) {
        if(a[0] == b[0]) return a[1] < b[1];
        return a[0] < b[0];
    });

    int cnt = 0, ans = 0;
    for(auto [x, y] : seg) {
        if(y == 0) {
            cnt++;
            ans = max(ans, cnt);
        } else {
            cnt--;
        }
    }

    cout << ans << "\n";

    return 0;
}

求最多不重叠区间的数量

给定\(n\)个区间,求最多不重叠的区间数。

解法

把区间按右端点从小到大排序,设\(maxr\)为第一个区间的右端点,然后枚举剩余的区间。如果枚举区间的左端点大于\(maxr\),则更新\(maxr\)为枚举区间的右端点,答案加1。

代码

#include<bits/stdc++.h>

using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;

    vector<array<int, 2>> seg(n);
    for(int i = 0; i < n; i++) {
        cin >> seg[i][0] >> seg[i][1];
    }

    sort(seg.begin(), seg.end(), [&](array<int, 2> &a, array<int, 2> &b) {
        return a[1] < b[1];
    });

    int ans = 1, maxr = seg[0][1];
    for(int i = 1; i < n; i++) {
        if(seg[i][0] > maxr) {
            ans++;
            maxr = seg[i][1];
        }
    }

    cout << ans << "\n";

    return 0;
}
posted @ 2023-07-20 01:38  wuyoudexian  阅读(22)  评论(0)    收藏  举报