区间 纪中 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.
posted @ 2016-07-13 17:09  一个响亮的蒟蒻  阅读(375)  评论(0编辑  收藏  举报