1. 程式人生 > >codefroces 946G Almost Increasing Array

codefroces 946G Almost Increasing Array

AC 要求 ret log 需要 inpu put example ace

Description
給你一個長度為$n$的序列$A$.現在準許你刪除任意一個數,刪除之後需要修改最小的次數使序列單調遞增。問最小次數。
$1≤n≤200000$
Examples
Input
5
5 4 3 2 1
Output
3
Input
5
1 2 8 9 5
Output
0

因為是修改形成遞增,所以假設修改$l+1~r-1$,那麽要求$a[r]-a[l]-1>=r-l-1$

於是有$a[r]-r>=a[l]-l$

於是就轉化為求最長不下降子序列

因為可以刪一個點,刪掉的點的後面的值減去的位權-1

設$f[i][0/1]$為第i位,是否刪了點

用二分優化,重新令$f[i][0/1]$表示長為i的序列末尾最小的數,是否刪點

註意刪了點的話位置會向前移,所以由$a[i]-i$變成$a[i]-i+1$

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 int inf=1e9,f[200005][2],a[200005],b[200005],n,tot,ans;
 8 int find(int x,int p)
 9 {
10   int l=1,r=n,as
=0; 11 while (l<=r) 12 { 13 int mid=(l+r)/2; 14 if (f[mid][p]>x)as=mid,r=mid-1; 15 else l=mid+1; 16 } 17 return as; 18 } 19 int main() 20 {int i,tmp1,tmp2; 21 cin>>n; 22 for (i=1;i<=n;i++) 23 { 24 scanf("%d",&a[i]); 25 f[i][0
]=f[i][1]=inf; 26 } 27 f[0][0]=f[0][1]=-inf; 28 for (i=2;i<=n;i++) 29 { 30 tmp1=find(a[i-1]-i+1,0);tmp2=find(a[i]-i+1,1); 31 f[tmp1][0]=a[i-1]-i+1; 32 f[tmp2][1]=a[i]-i+1; 33 f[tmp1][1]=min(f[tmp1][1],f[tmp1][0]); 34 ans=max(ans,max(tmp1,tmp2)); 35 } 36 cout<<n-ans-1; 37 }

codefroces 946G Almost Increasing Array