• nlogn求最长不上升子序列


    这种问题一般都比较熟悉,我们先看n^2的算法

    导弹拦截

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 106  解决: 61
    [提交][状态][讨论版]

    题目描述

    某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意 的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所 有的导弹。
    输入导弹一次飞来的高度(雷达给出的高度不大于30000的正整数)。计算这套系统最多能拦截多少导弹。

    输入

    n颗依次飞来的导弹高度,导弹颗数<=1000。

    输出

    一套系统最多拦截的导弹数。

    样例输入

    7 300 250 275 252 200 138 245

    样例输出

    5
    令f[i]表示前i个数的最长序列长度f[j]=max(f[j],f[i]+1)i<j且a[i]>=a[j]
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,a[1005],f[1005],ans;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
        {
            f[i]=1;
            for(int j=1;j<i;j++)
            if(a[j]>=a[i])f[i]=max(f[i],f[j]+1);
        }
        for(int i=1;i<=n;i++)
        ans=max(ans,f[i]);
        cout<<ans<<endl; 
     } 

    但是在一些n=100000的题目上O(n^2)的算法会时间超限。我们考虑优化这一算法。令B[i]=长度位i的序列最后一个一个字符的最大值。

    对于新进来的一个数,我们看其能否跟新B数组中的一个值。如何跟新一个值呢?二分查找。

    #include<iostream>
    #include<cstdio>
    #include<algorithm> 
    using namespace std;
    int n,B[100005],a[100005],len;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        B[1]=-a[1],len=1;
        for(int i=2;i<=n;i++)
        {
            if(-a[i]>=B[len]) B[++len]=-a[i];
            else
            {
                int pos=upper_bound(B+1,B+len,-a[i])-B;
                B[pos]=-a[i];
            }
        }
        cout<<len<<endl;
    }

    就是很短的代码实现了nlogn的类lis功能。

     
  • 相关阅读:
    P4318 完全平方数 [二分答案+容斥+莫比乌斯函数]
    P2522 [HAOI2011]Problem b
    莫比乌斯反演学习笔记
    UVALive646 Deranged Exams [容斥+排列组合]
    HDU5514 Frogs [容斥(II)]
    P2567 [SCOI2010]幸运数字 [容斥+有技巧的搜索]
    微信api退款操作
    类中或者是程序集中,根据虚拟路径获取绝对路径
    加载程序集中内嵌资源
    .NET Framework 框架简述01
  • 原文地址:https://www.cnblogs.com/dancer16/p/7241509.html
Copyright © 2020-2023  润新知