zoukankan      html  css  js  c++  java
  • 最长上升子序列 nlogn

    最长上升子序列有dp的写法

    f[i]:=max(f[j])+1;

    f[1]:=1;

    var
    a:array[0..1000,1..2] of longint;
    sum,max,i,j,k,n:longint;
    begin
    read(n);
    for i:=1 to n do
    read(a[i,1]);
    a[n,2]:=1;
    for i:=n-1 downto 1 do
    begin
    max:=0;
    for j:=i+1 to n do
    if (a[i,1]<a[j,1])and(a[j,2]>max) then
    max:=a[j,2];
    a[i,2]:=max+1;
    end;
    sum:=0;
    for i:=1 to n do
    if sum<a[i,2] then
    sum:=a[i,2];
    write(sum);
    end.
    View Code

    时间复杂度为n^2

    今天oyzx强者教了我一些写法,为nlogn

    方法如下:

    1.利用一个单调栈,如果栈顶小于待插入的元素就直接插入,更新答案,否则就用二分在栈中找到第一个比它大的元素然后替换

    var
    a,c:array[0..1000] of longint;
    top,anss,x,i,k,n:longint;
    function find(x:longint):longint;
    var
    ans,re,pre,mid:longint;
     begin
     pre:=1;
     re:=top;
     ans:=0;
     while pre<=re do
       begin
       mid:=(pre+re) div 2;
       if x>c[mid] then
       begin
         pre:=mid+1;
         if mid>ans then
         ans:=mid;
       end
        else
         re:=mid-1;
     end;
     find:=ans;
    end;
    begin
    anss:=0;
    read(n);
    for i:=1 to n do
     read(a[i]);
     top:=1;
     c[top]:=a[1];
     for i:=2 to n do
      begin
       if c[top]<a[i] then
        begin
         top:=top+1;
         c[top]:=a[i];
        end
       else
       begin
         x:=find(a[i]);
         c[x+1]:=a[i];
       end;
        if anss<top then
         anss:=top;
      end;
      writeln(anss);
     end.
    View Code

    2.用树状数组优化,记录1--a[i]中最大的f[i],由于a[i]可能达到10^9,要用离散化

    var
    s,a:array[0..1000] of longint;
    c,f:array[0..10000] of longint;
    x,ans,i,j,k,n:Longint;
    procedure swap(var x,y:longint);
    var
    w:longint;
     begin
     w:=x; x:=y; y:=w;
     end;
    procedure sort(l,r:longint);
    var
    i,j,w,x:longint;
     begin
     i:=l; j:=r;
     x:=a[(l+r) div 2];
     repeat
     while a[i]<x do
      inc(i);
     while a[j]>x do
      dec(j);
      if not(i>j) then
       begin
       swap(a[i],a[j]);
       inc(i);
       dec(j);
       end;
      until i>j;
       if i<r then
       sort(i,r);
       if l<j then
       sort(l,j);
    end;
     
    function max(x,y:longint):longint;
    begin
     if x>y then
     exit(x)
     else exit(y);
    end;
    function find(x:longint):longint;
     var
    ans,pre,re,mid:longint;
     begin
     ans:=0;
     pre:=0;
     re:=n;
     while pre<=re do
      begin
      mid:=(pre+re) div 2;
       if x>a[mid] then
       begin
        pre:=mid+1;
        if mid>ans then
        ans:=mid;
       end
       else re:=mid-1;
      end;
      find:=ans;
    end;
    function down(x:longint):longint;
    begin
    down:=x and -x;
    end;
    procedure up(x,s:longint);
    begin
    while x<=10000 do
     begin
     c[x]:=max(c[x],s);
     x:=x+down(x);
     end;
    end;
    function get(x:longint):longint;
    var
    ans:longint;
    begin
    ans:=0;
    while x>0 do
     begin
     if c[x]>ans then
     ans:=c[x];
     x:=x-down(x);
     end;
     get:=ans;
    end;
    begin
    read(n);
    for i:=1 to n do
     read(a[i]);
     s:=a;
     sort(1,n);
     for i:=1 to n do
      begin
      x:=find(s[i]);
      f[i]:=get(x)+1;
      up(x+1,f[i]);
      end;
      for i:=1 to n do
      if f[i]>ans then
      ans:=f[i];
      writeln(ans);
     end.
    View Code

     

  • 相关阅读:
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 454 四数相加 II
    Java实现 LeetCode 454 四数相加 II
    Java实现 LeetCode 454 四数相加 II
    FFmpeg解码H264及swscale缩放详解
    linux中cat more less head tail 命令区别
    C语言字符串操作总结大全(超详细)
    如何使用eclipse进行嵌入式Linux的开发
  • 原文地址:https://www.cnblogs.com/fhlxpyz/p/6062669.html
Copyright © 2011-2022 走看看