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;
    }
    
  • 相关阅读:
    邁向 RHCE 之路 (Day26)
    apache 2.2设置单IP多端口的虚拟主机
    error: invalid use of incomplete type
    C++常函数
    C++ 函数对象
    :-1: error: [debug/moc_gotocelldialog.cpp] Error 2
    C++中虚析构函数的作用
    tomcat启动报错:org.springframework.beans.factory.BeanCreationException
    Linux环境抓包命令
    数据库中通过group by找出表中的重复数据
  • 原文地址:https://www.cnblogs.com/NLDQY/p/10339592.html
Copyright © 2011-2022 走看看