模拟赛33 T2incr(luogu p3902 递增)

传送门

然而考试的时候并没有看出来是线性dp


那么复习一下线性dp lis问题

LIS 最长上升子序列

可以用dp求解 复杂度O(n^2)

定义dp[i] 表示a[i]为结尾的“最长上升子序列”的长度

转移方程 dp[i]=max{dp[j]+1} (0<=j<i,a[j]<a[i])

边界也很好理解 就是dp[0]=0

那么目标就是max{dp[i]}


那么这道题就可以找到最长上升子序列的个数

用总个数减最长上升子序列去的个数 就是答案

具体看代码

#include<bits/stdc++.h>
using namespace std;
int n,len;
const int mxn=100005;
int a[mxn],dp[mxn];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        a[i]-=i;
    }
    dp[++len]=a[1];
    for(int i=2;i<=n;i++){
        if(dp[len]<=a[i]) dp[++len]=a[i];
        else{
            int k=lower_bound(dp+1,dp+len+1,a[i])-dp;//二分查找第一个大于等于a[i]的元素位置 
//            cout<<dp<<" "<<lower_bound(dp+1,dp+len+1,a[i]);
            dp[k]=a[i]; 
        } 
    }
    cout<<n-len;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/duojiaming/p/11668099.html
今日推荐