zoukankan      html  css  js  c++  java
  • 洛谷P3902 递增

    这里写图片描述
    .
    .
    .
    .
    .

    分析

    定义f[i]表示以位置i为结尾的LIS长度。边界条件为f[0]=1,状态转移方程为

    f[i]=max(f[i],f[j]+1)(j=1…i-1 a[i]>=a[j])

    我们观察到,f[i]的值由前面的数字推得,所以我们只要从前往后转移,就可以保证每次使用的数字都是已经确定的值。

    考虑两个数a[x]和a[y],若x< y且f[x]==f[y],那么在转移的过程中,选择a[x]更有潜力,可以获得最优的值,所以当f数组的值一样时,应选择最小的数。

    按照f[i]==k分类,记录f[i]==k的所有i的最小值,f有两个特点:

    (1)f[i]在计算过程中单调不升

    (2)f数组是有序的,f[i]<=f[i+1]

    根据这些性质,可以方便地求解:

    (1)设当前求出的LIS长度为ans(初始值为1),当前元素为a[x]

    (2)如果a[x]>f[ans],直接加入f数组的末尾,且ans++;否则在f数组中二分查找,找到第一个比a[x]小的数字f[k],f[k+1]=a[x],这样做保证a[x]<=f[k+1](根据性质1,2)

    (3)最后的ans即为答案
    .
    .
    .
    .
    .

    程序:
    #include<iostream>
    using namespace std;
    int a[100000],f[100000],n,ans,tj;
    
    int work(int w,int l,int r)
    {
        while (l<r)
        {
            int mid=(l+r)/2;
            if (w>=f[mid]) l=mid+1;else r=mid;
        }
        return l;
    }
    
    int main()
    {
        cin>>n;
        for (int i=0;i<n;i++)
        cin>>a[i];
        f[1]=a[0]; 
        for (int i=1;i<n;i++)
        {
            if (f[ans]<a[i]) tj=++ans;else tj=work(a[i],1,ans+1);
            f[tj]=a[i];
        }
        cout<<n-ans;
        return 0;
    }
  • 相关阅读:
    2018JAVA面试题附答案
    微服务概述
    Java后台开发面试题总结
    郁金香搜索引擎方案
    单点登录
    Redis为什么是单线程
    数据库原理-范式
    权限分配之一级菜单优化添加和编辑页面图标
    权限分配之一级菜单保留原搜索条件
    django分页的东西, 不详细, 但是也足够了。
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/9499908.html
Copyright © 2011-2022 走看看