题意:
可以将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; }
