题解 | 区间覆盖问题的变形

代理服务器

https://www.nowcoder.com/practice/1284469ee94a4762848816a42281a9e0

时间复杂度:O(mlogm)

区间覆盖问题

给定n个小区间和一个范围[a, b],选择尽量少的区间,使得[a, b]能够被完全覆盖。

解法:贪心

如果有区间x和y,x包含了y,显然选择x这个大区间更好。

因此考虑对每个区间按左端点升序排序,从第一个小区间开始选择,每次选择区间左端点在目标区间内右端点尽可能大的区间。每次选择区间后更新目标区间(左端点更新为选中区间的右端点+1)。

排序开销:O(nlogn)

选区间开销:O(n)

总时间复杂度:O(nlogn)

区间预处理

显然,本题没有明说各个小区间,因此需要预处理出小区间。

我们可以把m个请求服务器看成[0,m-1]的区间。

每个代理服务器在需要切换之前(后)看成小区间。

如请求服务器顺序为ABBA,那么A对应的小区间有[1,2],B对应的小区间有[0,0]、[3,3]

源码

//
// Created by Zed on 2024/1/22.
//
#include <iostream>
#include <unordered_map>
#include <algorithm>
#include <map>

using namespace std;
const int MAXN = 1e3 + 100;

struct Interval {
    int a, b;

    bool operator<(const Interval interval) {
        if (a != interval.a) {
            return a < interval.a;
        }
        return b > interval.b;
    }
} intervals[MAXN];


int main() {
    int n, m;
    while (cin >> n) {
        map<string, int> dict;//维护上一次IP出现的下标
        for (int i = 0; i < n; ++i) {
            string tmp;
            cin >> tmp;
            dict[tmp] = -1;
        }
        int cnt = 0;//区间数
        cin >> m;
        for (int i = 0; i < m; ++i) {
            string tmp;
            cin >> tmp;
            if (dict.count(tmp)) {
                if (i - 1 >= dict[tmp] + 1) {
                    intervals[cnt].a = dict[tmp] + 1;
                    intervals[cnt].b = i - 1;//不包含端点
                    cnt++;
                }
                dict[tmp] = i;
            }
        }
        for (const auto &item: dict) {
            if (m - 1 >= item.second + 1) {
                intervals[cnt].a = item.second + 1;
                intervals[cnt].b = m - 1;//不包含端点
                cnt++;
            }
        }
        sort(intervals, intervals + cnt);
        int ans = -1;
        int l = 0;
        int j = 0;
        while (l <= m - 1 && j < cnt) {
            if (intervals[j].a > l) {
                ans = -1;
                break;
            }
            int tmp_l = l;
            while (j < cnt && intervals[j].a <= l) {
                tmp_l = max(intervals[j].b + 1, tmp_l);
                j++;
            }
            l = tmp_l;
            ans++;
        }
        cout << ans << endl;
    }
}

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务