zoukankan      html  css  js  c++  java
  • POJ 1631 Bridging signals DP(最长上升子序列)

    最近一直在做《挑战程序设计竞赛》的练习题,感觉好多经典的题,都值得记录。

    题意:给你t组数据,每组数组有n个数字,求每组的最长上升子序列的长度。

    思路:由于n最大为40000,所以n*n的复杂度不够了,会超时。

       书上状态方程换成了d[i]——以长度为i+1的上升子序列中末尾元素的最小值。

       那么我们在遍历第i个元素时候,以这个元素为末尾元素的最长子序列也就是在d[i]中找到一个小于num[i]的最大值,然后在这个序列末尾加上num[i]

       显然,我们在查找时便可以利用二分搜索,从而把复杂度从原来的n变为了logn,总复杂度从n*n变成了nlogn

       

       d[i]已经保证了长度为i+1的上升子序列末尾元素的最小值,那么对于d[i+1]长度为i+2的子序列里面,要获得最长,自然就要从长度为i+1的子序列中,挑选末尾元素为最小的子序列后面添加元素。所以d[i+1] > d[i],d数组是一个递增的数组,所以就能用二分搜索了。

      lower_bound(d,d+n,num[i]); //默认数组d为上升数组,返回第一个大于等于num[i]的指针。
      lower_bound(d,d+n,num[i],greater<int>()); //表达数组d为下降数组,返回第一个小于等于num[i]的指针。

    AC代码:

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    const int N = 40005;
    const int INF = 0X3F3F3F3F;
    int n,t,num[N],d[N];
    //d[i] = 长度为i+1的上升子序列中末尾元素的最小值,不存在则INF 
    void solve()
    {
    	for(int i = 0; i < n; i++)
    		d[i] = INF;
    	for(int i = 0; i < n; i++)
    	{
    		scanf("%d", num+i);
    		*lower_bound(d,d+n,num[i]) = num[i];
    	}
    	printf("%d
    ", lower_bound(d,d+n,INF) - d);
    }
    int main()
    {
    	scanf("%d", &t);
    	while(t--)
    	{
    		scanf("%d", &n);
    		solve();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    对软件工程课程的期望
    自我介绍
    新目标
    课后作业-阅读任务-阅读笔记-4
    20150914-构建之法:现代软件工程-阅读笔记
    团队编程项目作业2-团队编程项目开发环境搭建过程
    团队编程项目作业2-团队编程项目设计文档
    个人-GIT使用方法
    结对编程项目作业2-结对编项目设计文档
    结对编程项目作业2-开发环境搭建过程
  • 原文地址:https://www.cnblogs.com/sevenun/p/5457290.html
Copyright © 2011-2022 走看看