题目描述

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

请写一个程序:

读入这些区间;

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

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

输入输出格式

输入格式

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

输出格式

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

样例

INPUT

5

5 6

1 4

10 10

6 9

8 10

OUTPUT

1 4

5 10

HINT

SOLUTION

差分

感觉差分是我们这种涉及区间的处理的问题的很重要的一个考虑方式啊qwq

接下来有10行废话。

这题不难。

我想过贪心,想过区间dp,想过建树bfs,就是没想到差分。

先看数据范围:\(3\leq n \leq 50000,1\leq a_i<b_i\leq 1000000\),

首先我们就把\(O(n^2)\)的方案给毙掉了。

这种题不是\(O(n)\)就是\(O(nlogn)\),对吧。

建树不好建,建了也不知道怎么写,毙掉。

就剩\(O(n)\)的了。

dp?怎么写啊?我不会,毙掉。

贪心把区间从头开始往后拓,直到出现断点?那万一全部连起来了呢?不好找断点,毙掉。

然后把目光放在这里:\(1\leq a_i<b_i\leq 1000000\),说不定有\(O(max(b_i))\)的写法呢?然后老老实实翻了题解。。。

所以我们考虑差分。

进来一个左端点就在相应位置+1,进来一个右端点就在相应位置-1,对,这就是典型的差分。

当我们的点的左边为正,而当前点为0,这说明有若干(也可能只有一)对区间从这里开始。

同理,当我们的点的右边为0,而当前点为0,这说明有若干(也可能只有一)对区间在这里完成了匹配,可以断开作为一段完整区间。

然后注意一下形同\([i,i]\)的区间要特判一下就可以了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define Min(a,b) ((a<b)?a:b)
#define Max(a,b) ((a>b)?a:b)
const int N=101000,M=1010000;
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-48;ch=getchar();}
return x*f;}
struct NODE{int d,u;}nd[N];
bool cmp(NODE a,NODE b) {return a.d<b.d;}
struct ITV{int l,r;}ans[N];
int n,itv[M],L=M,R=0;
int main(){
int i,j;
n=read();int cnt=0;
for (i=1;i<=n;++i){
nd[++cnt].d=read();nd[cnt].u=1;L=Min(L,nd[cnt].d);R=Max(R,nd[cnt].d);
nd[++cnt].d=read();nd[cnt].u=-1;L=Min(L,nd[cnt].d);R=Max(R,nd[cnt].d);}
memset(itv,0,sizeof(itv));
sort(nd+1,nd+1+cnt,cmp);
int p=1;cnt=0;
for (i=L;i<=R;++i){
itv[i]=itv[i-1];int flg=0,rec=0;
while ((nd[p].d==i)&&(p<=2*n)) {flg=1;rec+=nd[p].u;itv[i]+=nd[p].u;p++;}
if ((!itv[i-1])&&(flg)&&(!rec)) {ans[++cnt].l=i;ans[cnt].r=i;}//对于[i,i]型区间的特判
if ((!(itv[i-1]))&&(itv[i])) ans[++cnt].l=i;
else if ((itv[i-1])&&(!(itv[i]))) ans[cnt].r=i;
}
for (i=1;i<=cnt;++i) printf("%d %d\n",ans[i].l,ans[i].r);
return 0;
}

最新文章

  1. Android多种进度条使用详解
  2. WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED解决方法
  3. Lab_4_SysOps_Monitoring_Linux_v2.5
  4. NP完全问题 NP-Completeness
  5. 边工作边刷题:70天一遍leetcode: day 74
  6. c# 匿名对象增加动态属性
  7. java.sql.DataTruncation: Data truncation
  8. Machine Learning - week 3
  9. JVM性能调优总结
  10. java知识点5
  11. Linux安装Tomcat-Nginx-FastDFS-Redis-Solr-集群——【第四集之安装Linux】
  12. RAID各种级别详细介绍
  13. Zookeeper系列六:服务器角色、序列化与通信协议、数据存储、zookeeper总结
  14. VMPlayer Ubuntu 16.04 Copy and Paste with Host 主机与宿机之间的复制粘贴
  15. Spring注解方式配置Redis
  16. C#_方法的重载
  17. Python 进阶必备函数
  18. 智能引导式报错(Class file name must end with .class)
  19. 新入职如何快速去了解一个Javaweb项目!
  20. jQuery的基本事件

热门文章

  1. 三、VIP课程:并发编程专题-&gt;01-并发编程之Executor线程池详解
  2. one_day_one_linuxCmd---scp命令
  3. 由AnnotatedElementUtils延伸的一些所思所想
  4. ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction hihocoder1870~1879
  5. servlet 3 通过编程的方式来配置ServletContext
  6. 13.docker 网络 docker NameSpace (networkNamespace)
  7. Java中:&gt;&gt;&gt;和&gt;&gt;区别
  8. Matlab:fsolve No solution found.
  9. ESLint javascript格式要求
  10. 2017年3月25日工作日志:Jquery使用小结[绑定事件判断、select标签、军官证正则]