# 最长上升子序列 nlogn

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
for i:=1 to n do
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

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;
for i:=1 to n do
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
for i:=1 to n do
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

posted @ 2016-11-15 16:52  jkl~  阅读(153)  评论(0编辑  收藏  举报