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;
    }
    

      

  • 相关阅读:
    poj 2406 Power Strings【最小循环节】
    hdoj 2087 剪花布条
    hdoj 1054 Strategic Game【匈牙利算法+最小顶点覆盖】
    hdoj 1151 Air Raid
    hdoj 2502 月之数
    hdoj 1862 EXCEL排序
    hdoj 1200 To and Fro
    hdoj 1150 Machine Schedule【匈牙利算法+最小顶点覆盖】
    hdoj 1068 Girls and Boys【匈牙利算法+最大独立集】
    uva1563
  • 原文地址:https://www.cnblogs.com/sevenun/p/5457290.html
Copyright © 2011-2022 走看看