題面
給一個長度10^5的非負序列,序列中的0可以任意換成任何數字(包括負數),問最長嚴格上升子序列長度。
輸入
第一行有一個數n代表序列長度
第二行有n個數字ai代表序列每個值是多少。
輸出
一行一個數字代表答案
樣例輸入
7
2 0 2 1 2 0 5
樣例輸出
5
數據規模
SOL
狀態轉移方程:
如果沒有0,那麼我們直接加上一個樹狀數組優化(線段樹或者二分什麼的也行)就可以過了
對於這道題,顯然,我們選擇最長的子序列向其中加0最優
但是可能出現多條最長子序列
爲了抵消這部分的影響,我們可以考慮對每一個非0的ai減去其前面0的個數再求
最後加上0的個數
等效於強制所有0都有貢獻,因爲強制一個0出現最多隻能使一個原來最長子序列裏的數不出現,所以不會影響答案
代碼:
#include<bits/stdc++.h>
using namespace std;
#define re register
inline int rd(){
int re data=0;static char ch=0;ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))data=(data<<1)+(data<<3)+(ch^48),ch=getchar();
return data;
}
const int N=1e5+5,M=1e5,S=1.1e6+1;
int n,a[N],f[N],z[N],ans,c[S];
#define lb(x) (x&-x)
inline void edit(int x,int v){for(;x<S;x+=lb(x))c[x]=max(c[x],v);}
inline int ask(int x,int re ret=0){for(;x;x-=lb(x))ret=max(ret,c[x]);return ret;}
signed main(){
n=rd();
for(int re i=1;i<=n;++i)a[i]=rd(),z[i]=(!a[i])?z[i-1]+1:z[i-1];
for(int re i=1;i<=n;++i){
if(!a[i])continue;
a[i]-=z[i],f[i]=ask(a[i]+n-1)+1,edit(a[i]+n,f[i]),ans=max(ans,f[i]);
}cout<<ans+z[n],exit(0);
}