题目描述 Description
给定x轴上的N(0<N<100)条线段,每个线段由它的二个端点a_I和b_I确定,I=1,2,……N.这些坐标都是区间(-999,999)的整数。有些线段之间会相互交叠或覆盖。请你编写一个程序,从给出的线段中去掉尽量少的线段,使得剩下的线段两两之间没有内部公共点。所谓的内部公共点是指一个点同时属于两条线段且至少在其中一条线段的内部(即除去端点的部分)。
输入描述 Input Description
输入第一行是一个整数N。接下来有N行,每行有二个空格隔开的整数,表示一条线段的二个端点的坐标。
输出描述 Output Description
输出第一行是一个整数表示最多剩下的线段数。
样例输入 Sample Input
3
6 3
1 3
2 5
样例输出 Sample Output
2
数据范围及提示 Data Size & Hint
0<N<100
思路:
贪心,用一个下标k记录之前线段的最右边的点为,考虑以下情况:
1.ai>=k,即当前线段和之前保留的线段不重叠,那么直接保留当前线段ans+1,更新k=bi
2.ai<k,当前线段和之前保留的线段有重叠,再分情况考虑:
①若bi<=k,证明当前线段完全被之前保留线段的区域包含(因为已经排序,所以当前线段的起点一定大于等于之前的线段,bi<k证明终点小于等于之前线段,所以被包含),那么证明当前线段更优(一条线段被另一条完全包含,显然取短的线段更优),更新k=bi,但是结果计数ans不变
②若bi>k,证明当前线段一部分和之前重叠,那么为了对后续线段影响最小,即k尽量小,当前线段被舍弃,结果计数ans不变
输入时注意保证ai<bi且升序排序。
源代码/pas:
type
point=record
x,y:longint;
end;
var
n,ans:longint;
t:array[1..100]of point;
procedure sort(l,r:longint);
var
x,y,key:longint;
temp:point;
begin
if l>=r then exit;
x:=l;
y:=r;
key:=t[l+random(r-l+1)].x;
repeat
while (t[x].x<key) do inc(x);
while (t[y].x>key) do dec(y);
if x<=y then
begin
temp:=t[x];
t[x]:=t[y];
t[y]:=temp;
inc(x);
dec(y);
end;
until x>y;
sort(l,y);
sort(x,r);
end;
procedure main;
var
i,k:longint;
begin
i:=1;
k:=t[1].y;
repeat
inc(i);
if t[i].x>=k then
begin
k:=t[i].y;
inc(ans);
end
else
if t[i].y<k then k:=t[i].y;
until i>=n;
end;
procedure init;
var
i:longint;
begin
readln(n);
for i:=1 to n do
with t[i] do
begin
readln(x,y);
if x>y then
begin
x:=x xor y;
y:=x xor y;
x:=x xor y;
end;
end;
sort(1,n);
end;
begin
init;
main;
writeln(ans+1);
end.