bzoj1669 [Usaco2006 Oct]Hungry Cows饥饿的奶牛(nlogn求最长不下降子序列)

304 篇文章 2 订阅
32 篇文章 0 订阅

就是求最长不下降子序列,改进了一下, nlogn 的做法。多记一个d数组,d[k]表示长度为k的不下降子序列末尾元素的最小值。考虑新进来一个元素a[i]:如果这个元素大于等于d[len],直接让d[++len]=a[i].如果这个元素小于d[len]呢?说明它不能接在最后一个后面了.准确的说,并不是接在谁后面。而是替换掉谁。因为它接在前面的谁后面都是没有意义的,再接也超不过最长的len,所以是替换掉别人。那么替换掉谁呢?就是替换掉那个最该被它替换的那个。也就是在d数组中第一个大于它的。第一个意味着前面的都小于等于它。假设第一个大于它的是d[j],说明d[1..j-1]都小于等于它,那么它完全可以接上d[j-1]然后生成一个长度为j的不下降子序列,而且这个子序列比当前的d[j]这个子序列更有潜力(因为这个数比d[j]小)。所以就替换掉它就行了,也就是d[j]=a[i]。其实这个位置也是它唯一能够替换的位置(前面的替了不满足d[k]最小值的定义,后面替换了不满足不下降序列)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 5005
using namespace std;
int n,a[N],d[N],len=0;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();
    for(int i=1;i<=n;++i) a[i]=read();
    d[++len]=a[1];
    for(int i=2;i<=n;++i){
        if(a[i]>=d[len]) d[++len]=a[i];
        else *upper_bound(d+1,d+len+1,a[i])=a[i];
    } 
    printf("%d\n",len);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值