分析:
给出N个数,其中0可以被替换成 0 ~ 9 的任何数字,问替换后这N个数的最长递增子序列的长度为多少?题解:
为了保证严格递增,我们把每一个数都减去这个数之前的0的个数,然后去掉0,做一次LIS求出长度,然后加上0的个数就是原来数列的LIS长度了。LIS模板:
int DP[Maxn];
int LIS(int arr[],int n)//arr为数列,n为数列长度,数列从0开始。
{
memset(DP, 0, sizeof(DP));
int i,top,mid,low,high;
top = 0;
DP[0] = -1;
for(i=0;i<n;i++)
{
if(arr[i]>DP[top])
DP[++top] = arr[i];
else
{
low = 1;
high = top;
while(low <= high)
{
mid = (low + high)/2;
if(arr[i] > DP[mid])
low = mid + 1;
else
high = mid - 1;
}
DP[low] = arr[i];
}
}
return top;
}
- AC代码:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#define Maxn 112345
using namespace std;
int N;
int a[Maxn];
int DP[Maxn];
int LIS(int arr[],int n)
{
memset(DP, 0, sizeof(DP));
int i,top,mid,low,high;
top = 0;
DP[0] = -1;
for(i=0;i<n;i++)
{
if(arr[i]>DP[top])
DP[++top] = arr[i];
else
{
low = 1;
high = top;
while(low <= high)
{
mid = (low + high)/2;
if(arr[i] > DP[mid])
low = mid + 1;
else
high = mid - 1;
}
DP[low] = arr[i];
}
}
return top;
}
int main()
{
int T;
scanf("%d", &T);
int ii =1;
while(T--)
{
memset(a, 0, sizeof(a));
scanf("%d", &N);
int Zero = 0;
int index = 0;
for(int i=0; i<N;i++)
{
int x;
scanf("%d", &x);
if(x) a[index++] = x - Zero;
else Zero++;
}
//cout << LIS(a,index) <<endl;
printf("Case #%d: %d\n", ii++, LIS(a,index)+Zero );
}
return 0;
}