区间 (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.

 

你可能感兴趣的:(OS)