Codeforces 946G Almost Increasing Array 动态规划

题意

给一个长度为n的序列a,每次操作可以将任意一个位置替换成任意数,问最少需要操作多少次满足去掉不超过1个元素后这是一个严格上升序列。
n 200000

分析

我们把a[i]变成a[i]-i,那么上升序列就变成了不上升序列。
如果没有去掉元素的条件的话,答案就是n-最长不上升子序列长度。
但现在可以去掉某个元素,那么在去掉这个数后,后面的数的标号就会减一,所以我们可以多设一维0/1来表示是否进行了删数操作,然后分别用a[i]-i和a[i]-i+1来更新即可。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

const int N=200005;
const int inf=2000000000;

int n,a[N],f[2][N];

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=0;i<=n;i++) f[0][i]=f[1][i]=inf;
    f[0][0]=-inf;
    int ls=0,ans=0;
    for (int i=1;i<=n;i++)
    {
        int s1=std::upper_bound(f[1],f[1]+n+1,a[i]-i+1)-f[1];
        ans=std::max(ans,s1);
        f[1][s1]=a[i]-i+1;
        f[1][ls]=std::min(f[1][ls],f[0][ls]);
        ans=std::max(ans,ls);
        ls=std::upper_bound(f[0],f[0]+n+1,a[i]-i)-f[0];
        f[0][ls]=a[i]-i;
    }
    printf("%d",n-ans-1);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_33229466/article/details/80780799