HDU 5773 最长上升子序列

题意 给出一个序列 问它的最长严格上升子序列多长 这个序列中的0可以被替代为任何数

n的范围给出了1e5 所以平常的O(n*n)lis不能用了

在kuangbin的模板里有O(nlogn)的模板 套上就可以过了

但是比赛的时候没有拿模板= =. 于是就想出了另外一个时间复杂度不明的办法= =.

将序列从前往后扫

设定一个数组a a[i]=z a[i]为当前i长度的上升子序列中的最小的尾数的大小 maxl为当前找出的最长的子序列长度

每次我们扫到一个数 都对0-maxl长度的a[i]进行判断 看能不能将他加到长度为i-1的序列的尾部 来优化a[i]使长度为i的序列的尾数更小

当遇到非0数的时候 只需要慢慢判断就好了 遇到0的时候 应当尽量的使0变换的数更小 则在优化的时候应当将0变为a[i-1]+1来与a[i]比较

最后的maxl即为答案

这个办法速度并不稳定 因为每次都要从0-maxl扫一遍 最差的时候是O(n*n)(当所给序列为上升序列时)

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<iostream>
using namespace std;
int n;
int a[100050]; /// every l - min wei
int maxl;
int main()
{
    int t;
    scanf("%d",&t);
    int tt=0;
    while(t--)
    {
        tt++;
        maxl=0;
        a[0]=-999999999;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            if(x!=0)
            {
                if(x>a[maxl]){
                    maxl++;
                    a[maxl]=x;
                }
                for(int k=maxl;k>=2;k--)
                {
                    if(x>a[k-1]&&x<a[k])
                        a[k]=x;
                }
                if(x<a[1])
                    a[1]=x;
            }
            else
            {
                maxl++;
                a[maxl]=a[maxl-1]+1;
                for(int k=maxl-1;k>=1;k--)
                {
                    if(a[k]>a[k-1]+1)
                        a[k]=a[k-1]+1;
                }
            }
        }
        printf("Case #%d: ",tt);
        printf("%d
",maxl);
    }
}

  

原文地址:https://www.cnblogs.com/rayrayrainrain/p/5726947.html