HihoCoder - 1305 经典问题 区间覆盖相减

本文介绍了一种计算两个区间集合差集长度的方法。通过离散化所有区间的端点并标记其所属集合,遍历这些端点来计算A-B的长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

C - 经典问题
You are given two interval collections A and B. Collection A has N intervals [ A1, A2 ], [ A3, A4 ], …, [ A2N-1, A2N ] and collection B has M intervals [ B1, B2 ], [ B3, B4 ], …, [ B2M-1, B2M ]. Your task is to calculate the length of A - B.
For example if A = {[2, 5], [4, 10], [14, 18]} and B = {[1, 3], [8,|15]}, the length of A - B ({(3, 8), (15, 18]}) is 8.

Input

Line 1: Two integers N and M (1 ≤ N, M ≤ 100000).

Line 2: 2*N integers, A1, A2, ..., A2N (1 ≤ Ai ≤ 100000000).

Line 3: 2*M integers, B1, B2, ..., B2M (1 ≤= Bi ≤ 100000000).

Output

The length of A - B.

Sample Input

3 2
2 5 4 10 14 18
1 3 8 15

Sample Output

8

分析:
题目的意思啊大概就是求区间集 A - B = A - A∩B. 将所有的区间端点在数轴上离散化,并做好相应标记(是A中还是B中的端点,记作A/B,是左端点还是右端点,记作L/R).

对于离散的点,从小到大遍历,如果满足BL = BR(B集的是个完整区间)并且AL > AR(A集的区间左端点多于右端点,说明右边必存在一端点覆盖左边B集完整区间),则用下一个端点减去当前端点.

数轴

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;

const int MAXN = 1e6 + 10;
int n,m;
struct node{
    ll val;
    char id[3];
    bool operator <(const node &t)const{
        return val < t.val;
    }
}rec[MAXN];

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    while(cin>>n>>m){
        int cnt = 0;
        for(int i=1;i<=n;i++){
            ll l,r;
            cin>> l >> r;
            rec[cnt].val = l,rec[cnt].id[0] = 'A',rec[cnt].id[1] = 'L';
            cnt++;
            rec[cnt].val = r,rec[cnt].id[0] = 'A',rec[cnt].id[1] = 'R';
            cnt++;
        }
        for(int i=1;i<=m;i++){
            ll l,r;
            cin>> l >> r;
            rec[cnt].val = l,rec[cnt].id[0] = 'B',rec[cnt].id[1] = 'L';
            cnt++;
            rec[cnt].val = r,rec[cnt].id[0] = 'B',rec[cnt].id[1] = 'R';
            cnt++;
        }
        sort(rec,rec+2*(n+m));//区间排序
        //for(int i=0;i<2*(m+n);i++)cout<< rec[i].val;
        ll ans = 0;
        ll AL = 0,AR = 0,BL = 0,BR = 0;
        for(int i=0;i<2*(m+n);i++){
            node e = rec[i];
            if(e.id[0] == 'A'){
                if(e.id[1] == 'L')AL++;
                else if(e.id[1] == 'R')AR++;
            }
            else if(e.id[0] == 'B'){
                if(e.id[1] == 'L')BL++;
                else if(e.id[1] == 'R')BR++;
            }
            if(AL > AR  && BL == BR){
                ans += rec[i+1].val - e.val;
            }
        }
        cout<< ans <<endl;
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值