题意:
可以将0替换成任意interger(包括负数),在此基础上求最长递增子序列。
思路:
将所有的0全部提取出来,求出此时序列的LIS(不含0的),这是针对0在子序列的外面的情况,如0,1,2,3,0.那么如果0在子序列中间怎么办?
很简单,把读入的非0的数的值减去这个数前面0的个数即可,
如1,2,0,3,4。在提取出0后序列其实为1,2,2,3,LIS的长度为3,加上0的个数则为答案。
#include<bits/stdc++.h>
using namespace std;
#define N 100005
template <class T> inline void in(T &x)
{
T f = 1;
char c;
while ((c = getchar()) < '0' || c > '9') if (c == '-') f = -1;
x = c - '0';
while ((c = getchar()) >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0';
x *= f;
}
int dp[N], sum[N], a[N], n;
bool vis[N];
void solve(int kase)
{
in(n);sum[0]=0;
memset(vis, false, sizeof(vis));
for(int i=1; i<=n; i++)
{
in(a[i]);
if(a[i]==0) sum[i]=sum[i-1]+1, vis[i]=true;
else sum[i]=sum[i-1], a[i]-=sum[i];
}
int ans=sum[n], cnt=0;
dp[0]=-1e9;
for(int i=1; i<=n; i++)
{
if(vis[i]) continue;
if(a[i]>dp[cnt]) dp[++cnt]=a[i];
else
{
int pos=lower_bound(dp, dp+cnt+1, a[i])-dp;
dp[pos]=a[i];
}
}
ans+=cnt;
printf("Case #%d: %d\n", kase, ans);
}
int main()
{
int t, kase=0;in(t);
while(t--)
{
solve(++kase);
}
return 0;
}