区间 纪中 1382 最长不上升子序列o(n logn)
Description
Alice收到一些很特别的生日礼物:区间。即使很无聊,Alice还是能想出关于区间的很多游戏,其中一个是,Alice从中选出最长的不同区间的序列,其中满足每个区间必须在礼物中,另序列中每个区间必须包含下一个区间。
编程计算最长序列的长度。
Input
输入文件第一行包含一个整数N(1<=N<=100000),表示区间的个数。
接下来N行,每行两个整数A和B描述一个区间(1<=A<=B<=1000000)。
Output
输出满足条件的序列的最大长度。
Sample Input
输入1:
3
3 4
2 5
1 6
输入2:
5
10 30
20 40
30 50
10 60
30 40
输入3:
6
1 4
1 5
1 6
1 7
2 5
3 5
Sample Output
输出1:
3
输出2:
3
输出3:
5
分析
隔壁的第一眼:
这尼玛不是最长不上升子序列么!!!
隔壁的第二眼:
这尼玛就是最长不上升子序列!!!
本着 竭尽所能的原则,他想都不想就打了O(n²)的原版。
于是n=100000的数据令他的代码
瞬间爆炸
所以,本着(抄标)学习的精神
我们找的o(n logn)的算法:点一下
话说我的快排和二分错了很久
代码
type
arry=array[0..100010] of longint;
var
x,y:array[0..100010] of longint;
f,b:array[0..100010] of longint;
ans:longint;
ls:longint;
i,j,k:longint;
n:longint;
function fdfdfd(l,r,x:longint):longint;
var
i,j,k:longint;
mid:longint;
begin
i:=l; j:=r;
while i<=j do
begin
mid:=i+(j-i) div 2;
if b[mid]>=x then i:=mid+1
else j:=mid-1;
end;
fdfdfd:=i;
end;
procedure qsort(var a,b:arry; l,r:longint);
var
i,j,k:longint;
mid,zzt:longint;
temp:longint;
begin
if l>=r then exit;
i:=l; j:=r;
mid:=a[(l+r) div 2];
zzt:=b[(l+r) div 2];
repeat
while (a[i]<mid) or ((a[i]=mid)and(b[i]>zzt)) do i:=i+1;
while (a[j]>mid) or ((a[j]=mid)and(b[j]<zzt)) do j:=j-1;
if i<=j
then
begin
temp:=a[i]; a[i]:=a[j]; a[j]:=temp;
temp:=b[i]; b[i]:=b[j]; b[j]:=temp;
i:=i+1; j:=j-1;
end;
until i>j;
qsort(a,b,l,j);
qsort(a,b,i,r);
end;
begin
readln(n);
for i:=0 to n do
b[i]:=-maxlongint;
for i:=1 to n do
begin
readln(x[i],y[i]);
end;
qsort(x,y,1,n);
for i:=1 to n do
begin
j:=fdfdfd(1,i,y[i]);
f[i]:=j;
if b[f[i]]<y[i] then b[f[i]]:=y[i];
end;
ans:=0;
for i:=1 to n do
if ans<f[i] then ans:=f[i];
write(ans);
end.