题目描述

现给定\(n\)个闭区间\([a_i, b_i],1 \leq i \leq n\)。这些区间的并可以表示为一些不相交的闭区间的并。你的任务就是在这些表示方式中找出包含最少区间的方案。你的输出应该按照区间的升序排列。这里如果说两个区间\([a, b]\)\([c, d]\)是按照升序排列的,那么我们有\(a \leq b<c \leq d\)

请写一个程序:

读入这些区间;

计算满足给定条件的不相交闭区间;

把这些区间按照升序输出。

输入输出格式

输入格式:

第一行包含一个整数\(n\)\(3 \leq n \leq 50000\),为区间的数目。以下\(n\)行为对区间的描述,第\(i\)行为对第\(i\)个区间的描述,为两个整数\(1 \leq ai < bi \leq 1000000\),表示一个区间\([a_i, b_i]\)

输出格式:

输出计算出来的不相交的区间。每一行都是对一个区间的描述,包括两个用空格分开的整数,为区间的上下界。你应该把区间按照升序排序。

输入输出样例

输入样例#1:

5
5 6
1 4
10 10
6 9
8 10

输出样例#1:

1 4
5 10

思路:考虑差分,每次输入\(x\)\(y\),于是x的度++,\(y\)的度,然后再扫一遍,累积从\(0\)到+的就是左端点,从+到\(0\)的就是右端点。

代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
#define maxn 1000007
using namespace std;
int n,a[maxn],b[maxn],num,maxx;
inline int qread() {
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) num=num*10+c-'0';
    return num*f;
}
int main() {
    n=qread();
    for(int i=1,x,y;i<=n;++i) {
        x=qread(),y=qread();
        a[x]++,b[y]++;
        maxx=max(maxx,max(x,y));
    }
    for(int i=1;i<=maxx;++i) {
        if(!num&&a[i]) printf("%d ",i);
        num+=a[i]-b[i];
        if(!num&&b[i]) printf("%d\n",i);
    }
    return 0;
}