区间 (vijos 1439) 题解

【问题描述】

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

【样例输入】

    5

    5 6

    1 4

    10 10

    6 9

    8 10

【样例输出】

     1  4

   5 10

【解题思路】

     本题为SDOI 2005 day2 第一题,是区间覆盖问题的变种,其实,看了问题描述后可能不太懂题目的意思,但是看完样例后就会发现,其实就是将一些连在一起的区间合并在一起,最后从小到大输出每个合并后的区间。既然要从小到大,那第一步自然是将每个区间以起点为关键字从小到大排序,然后从第二个区间开始,每个区间与前一个选的区间进行比较,若连在一起,则合并区间,否则,新开一个区间,将这个区间存入新开的区间。注意:除了判断是否连在一起,还要判断终点的大小,如果终点大一些才存,否则无视该区间。

【代码实现】

 1 type rec=record
 2      a,b:longint;
 3 end;
 4 var c,d:array[1..50000] of rec;
 5     i,j,n,m,ans,r,w:longint;
 6 procedure sort(l,r:longint);
 7 var
 8  i,j,x:longint;
 9  y:rec;
10 begin
11  i:=l;
12  j:=r;
13  x:=c[(l+r) div 2].a;
14  repeat
15   while c[i].a<x do
16    inc(i);
17   while x<c[j].a do
18    dec(j);
19   if not(i>j) then
20    begin
21     y:=c[i];
22     c[i]:=c[j];
23     c[j]:=y;
24     inc(i);
25     j:=j-1;
26    end;
27  until i>j;
28  if l<j then
29   sort(l,j);
30  if i<r then
31   sort(i,r);
32 end;
33 begin
34  readln(n);
35  for i:=1 to n do
36   with c[i] do
37    readln(a,b);
38  sort(1,n);
39  w:=1;d[1].a:=c[1].a;d[1].b:=c[1].b;
40  for i:=2 to n do
41   if (c[i].a<=d[w].b)and(c[i].b>=d[w].b) then//判断区间是否重合,若重合,更新终点
42    d[w].b:=c[i].b
43   else
44    if c[i].a>d[w].b then//若不重合,新开一个区间
45     begin
46      inc(w);
47      d[w].a:=c[i].a;
48      d[w].b:=c[i].b;
49     end;
50  for i:=1 to w do
51   with d[i] do
52    writeln(a,' ',b);
53 end.

 

posted @ 2015-05-10 15:56  PbTfcLx  阅读(392)  评论(0编辑  收藏  举报