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