zoukankan      html  css  js  c++  java
  • 最长不下降子序列

    最近想复习dp,于是先来水一篇博客。。。

    如何来求一个一串长度为(n)的数列的最长不下降子序列呢?

    (dp[i])表示所有长度为(i)的不下降子序列的最小结尾数字。

    也就是说(dp[i]={min(j)|len[j]=i})(len[j])表示以(j)结尾的不下降子序列长度(实际代码并不要用上这个数组)。

    然后就可以愉快的开始dp啦!

    初始化(dp[1]=a[1],ans=1),从2开始dp

    对于每一个(a[i]),若(a[i]ge dp[ans]),那么它就可以更新当前答案,所以就令(dp[++ans]=a[i])

    若小于呢?则我们需要用上dp数组的单调性了。

    我们先来看看dp数组的定义:(dp[i]={min(j)|len[j]=i})

    再结合更新过程,我们显然可以得出(dp[i]ge dp[i-1])的性质

    所以如果小于,我们就在(dp[1\,\,to\,\,ans])中找到第一个大于(a[i])的数,把它替换成(a[i])

    此时,因为它是第一个大于(a[i])的,所以它之前的数肯定都小于(a[i]),所以(a[i])完全可以代替它,且因为(a[i])比它要小,所以带来的价值会更高(贪心)。

    具体实现我们可以用STL中的upper_bound(毕竟学的都是C with STL 滑稽.jpg)。时间复杂度(O(n\,\,log\,\,n))

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    int n,ans;
    int a[100001],dp[100001];
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	dp[1]=a[1];ans=1;
    	for(int i=2;i<=n;i++){
    		if(a[i]>=dp[ans]) dp[++ans]=a[i];
    		else {
    			int x=upper_bound(dp+1,dp+ans+1,a[i])-dp;
    			dp[x]=a[i];	
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    【原创】大数据基础之调度框架
    使用mysql索引的规则
    mysql分区(partition)
    mysql-主从复制(二)
    yum 一些命令
    centos 升级php、mysql(webtatic)
    Linux 查找文件方法
    mysql-备份和还原(普通还原和binlog还原)
    mysql-主从复制(一)
    GSAP JS基础教程--动画的控制及事件
  • 原文地址:https://www.cnblogs.com/NLDQY/p/10339592.html
Copyright © 2011-2022 走看看