HDU 5773 The All-purpose Zero 2016多校第四场1010 LIS
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5773
题意:给你一个序列,找出最大上升子序列的长度,其中序列中的0可以变为任意整数(正负都可以)。
题解:对于这道题很明显是LIS,但是加多一个对0的操作。显然地,对于0,我们需要考虑把它放或者不放入最优解中。那么有什么情况是不放入0的?举个例子,现有序列4 0 5,对于0来说无论它变为什么都不能改变最终结果,但可以把0变为4或者5,也就是说我们可以把所有的0放进去。在处理不改变最终结果的0的时候,只需要用0把后面的替换掉即可,也就是例子中把0变为5,序列变成4 5 5。那么对于4 0 0 5这种情况0怎么处理?我们不能把两个0都变成5,并且必须把两个0变成不相等的两个数。也就是说所有的0都不相等。那么我们可以根据一一对应的思想(离散数学)把所有的0都变为不相等的整数。我们考虑任意相邻的两个0(下标分别为i,j),发先i、j前面0的个数刚好是相差1的。于是,我们可以将每个权值S[i]减去i前面0的个数,这样就保证了所有的0不相等,再做LIS,就能保证结果是严格递增的。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int T;
int n;
int ar[100005];
int main()
{
cin>>T;
for(int kase=1;kase<=T;kase++)
{
memset(ar,0,sizeof(ar));
int m=0;
int tot=0;
scanf("%d",&n);
int a;
for(int i=0;i<n;i++)
{
scanf("%d",&a);
if(a==0)
tot++;
else
{
a-=tot;
int p=lower_bound(ar,ar+m,a)-ar;
ar[p]=a;
m=max(m,p+1);
}
}
printf("Case #%d: %d\n",kase,m+tot);
}
return 0;
}