最长上升子序列(LIS.pas/c/cpp)

 最长上升子序列(LIS.pas/c/cpp)

  
LIS 问题是最经典的动态规划基础问题之一。如果要求一个满足一定条件的最长上升子序列,你还能解决吗?
  给出一个长度为N 整数序列,请求出它的包含第K个元素的最长上升子序列。
  例如:对于长度为 6的序列<2,7,3,4,8,5>,它的最长上升子序列为<2,3,4,5>,但如果限制一定要包含第2个元素,那么满足此要求的最长上升子序列就只能是<2,7,8>了。
 
输入数据
  第一行为两个整数N,K,如上所述。
  接下来是 N个整数,描述一个序列。
 
输出数据
  请输出两个整数,即包含第K 个元素的最长上升子序列长度。
 
样例
输入
8 6
65 158 170 299 300 155 207 389
输出
4

======================

先删点...

保持k左边的小于a[k],k右边的>a[k];

数据范围,根据单调性二分优化...

------------------

注意题目条件:

最长上升....而不是最长不下降...

======================

var
  n,k:longint;
  num,g:array[0..200000]of longint;

procedure init;
begin
  assign(input,'lis.in');
  assign(output,'lis.out');
  reset(input);
  rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure main;
var
  i:longint;
  tot,t,ans,max:longint;
  l,r,m:longint;
begin
  readln(n,k);
  for i:=1 to n do read(num[i]);

  if (n=0) or (k=0) then
    begin
      writeln('0');
      terminate;
    end;
  tot:=0; t:=num[k];
  
  for i:=1 to k-1 do
    begin
      if num[i]<t then
        begin
          inc(tot);
          num[tot]:=num[i];
        end;
     end;
     
  inc(tot);
  num[tot]:=t;
  
  for i:=k+1 to n do
    begin
      if num[i]>t then
        begin
          inc(tot);
          num[tot]:=num[i];
        end;
    end;

  fillchar(g,sizeof(g),$7);
  g[1]:=num[1];
  max:=0;
  for i:=2 to tot do
    begin
      l:=1; r:=tot;
      ans:=0;
      while l<=r do
        begin
          m:=(l+r) shr 1;
          if g[m]<num[i] then
           begin
             ans:=m;
             l:=m+1;
           end
           else   begin
                    r:=m-1;
                  end;
        end;
      if g[ans+1]>num[i] then g[ans+1]:=num[i];
      if max<ans+1 then max:=ans+1;
    end;
  writeln(max);
end;

begin
  init;
  main;
  terminate;
end.


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值