本体来自 hihocoder #1305
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
给定两个区间集合 A 和 B,其中集合 A 包含 N 个区间[ A1, A2 ], [ A3, A4 ], ..., [ A2N-1, A2N ],集合 B 包含 M 个区间[ B1, B2 ], [ B3, B4 ], ..., [ B2M-1, B2M ]。求 A - B 的长度。
例如对于 A = {[2, 5], [4, 10], [14, 18]}, B = {[1, 3], [8, 15]}, A - B = {(3, 8), (15, 18]},长度为8。
输入
第一行:包含两个整数 N 和 M (1 ≤ N, M ≤ 100000)。
第二行:包含 2N 个整数 A1, A2, ..., A2N (1 ≤ Ai ≤ 100000000)。
第三行:包含 2M 个整数 B1, B2, ..., B2M (1 ≤= Bi ≤ 100000000)。
输出
一个整数,代表 A - B 的长度。
样例输入
3 2 2 5 4 10 14 18 1 3 8 15
样例输出
8
分析
这道题的思路并不复杂,很容易想到,我们可以先对A、B中的区间进行合并,得到一些彼此不交的区间,这些区间按位置排序,然后对于A中每个区间,考察所有覆盖住该区间的B中区间,则该区间对A-B的贡献就是这些B中区间之间的缝隙。显然,这样做我们得到的算法的复杂度是O(NlogN)。
代码如下:
#include<iostream> #include<vector> #include<deque> #include<stack> #include<string> #include<algorithm> #include<string.h> #include<sstream> using namespace std; struct Interval { int start; int end; Interval() :start(0), end(0) {} Interval(int a, int b) :start(a), end(b) {} }; const int max_n = 100000; Interval a[max_n]; Interval b[max_n]; bool in_cmp(const Interval& a, const Interval& b){ return a.start < b.start; } bool is_overlap(Interval& a, Interval& b){ if (a.end < b.start) return false; if (b.end < a.start) return false; return true; } Interval my_union(Interval& a, Interval& b){ int start = min(a.start, b.start); int end = max(a.end, b.end); Interval u(start, end); return u; } void union_in(int N, int M, vector<Interval>& a_u, vector<Interval>& b_u) { sort(a, a + N, in_cmp); int i = 0; while (i < N) { Interval now_in = a[i]; int j = i + 1; while (j < N){ if (is_overlap(a[j], now_in)) { now_in = my_union(now_in, a[j]); ++j; } else break; } a_u.push_back(now_in); i = j; } sort(b, b + M, in_cmp); i = 0; while (i < M) { Interval now_in = b[i]; int j = i + 1; while (j < M){ if (is_overlap(b[j], now_in)) { now_in = my_union(now_in, b[j]); ++j; } else break; } b_u.push_back(now_in); i = j; } } int sol(vector<Interval> &a_u, vector<Interval> &b_u) { int res = 0; auto it_a = a_u.begin(); auto it_b = b_u.begin(); while (it_a != a_u.end()) { if (it_b == b_u.end() || (it_b->end >= it_a->start && !is_overlap(*it_b, *it_a))) { res += it_a->end - it_a->start; ++it_a; } else if (it_b->end < it_a->start) { ++it_b; } else { if (it_b->start > it_a->start) res += it_b->start - it_a->start; auto it_be = it_b + 1; while (it_be != b_u.end() && is_overlap(*it_be, *it_a)) { res += it_be->start - (it_be - 1)->end; ++it_be; } --it_be; if (it_be->end < it_a->end) res += it_a->end - it_be->end; ++it_a; it_b = it_be; } } return res; } int main() { int N, M; cin >> N >> M; for (int i = 0; i < N; ++i) { int x, y; cin >> x >> y; a[i].start = x; a[i].end = y; } for (int i = 0; i < M; ++i) { int x, y; cin >> x >> y; b[i].start = x; b[i].end = y; } vector<Interval> a_u; vector<Interval> b_u; union_in(N, M, a_u, b_u); int res = sol(a_u, b_u); cout << res << endl; //system("pause"); return 0; }
时间: 2024-10-21 08:23:35