最长上升子序列有dp的写法
f[i]:=max(f[j])+1;
f[1]:=1;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.
时间复杂度为n^2
今天oyzx强者教了我一些写法,为nlogn
方法如下:
1.利用一个单调栈,如果栈顶小于待插入的元素就直接插入,更新答案,否则就用二分在栈中找到第一个比它大的元素然后替换
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.
2.用树状数组优化,记录1--a[i]中最大的f[i],由于a[i]可能达到10^9,要用离散化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.