区间求差

本体来自 hihocoder #1305

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

给定两个区间集合 A 和 B,其中集合 A 包含 N 个区间[ A1A2 ], [ A3A4 ], ..., [ A2N-1A2N ],集合 B 包含 M 个区间[ B1B2 ], [ B3B4 ], ..., [ B2M-1B2M ]。求 A - B 的长度。

例如对于 A = {[2, 5], [4, 10], [14, 18]}, B = {[1, 3], [8, 15]}, A - B = {(3, 8), (15, 18]},长度为8。

输入

第一行:包含两个整数 N 和 M (1 ≤ NM ≤ 100000)。

第二行:包含 2N 个整数 A1A2, ..., A2N (1 ≤ Ai ≤ 100000000)。

第三行:包含 2M 个整数 B1B2, ..., 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;
}

 

posted @ 2017-06-03 14:00  mhkds  阅读(316)  评论(0编辑  收藏  举报