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