HDU-5773 The All-purpose Zero

From: HDU-5773

Problem Description:

?? gets an sequence S with n intergers(0 < n <= 100000,0<= S[i] <= 1000000).
?? has a magic so that he can change 0 to any interger(He does not need to change all 0 to the same interger).
?? wants you to help him to find out the length of the longest increasing (strictly) subsequence he can get.

Input:

The first line contains an interger T,denoting the number of the test cases.(T <= 10)
For each case,the first line contains an interger n,which is the length of the array s.
The next line contains n intergers separated by a single space, denote each number in S.

Output:

For each test case, output one line containing “Case #x: y”(without quotes), where x is the test case number(starting from 1) and y is the length of the longest increasing subsequence he can get.

 

   很显然,这是一道LIS,但也很显然,ta不纯,那个总受通用“0”让我们很头疼;所以,我们要想办法干掉"0",让ta变纯。

  由于“0”是通用的,那么把"0"全选进来一定是最优的,或曰:在最优解中,“0”位于两个连续自然数之间,那“0”是没有办法选的。但仔细想想,干掉一个,再把可爱的通用“0”加进来,仍然是最优解。至此,思路已经很清晰了,干掉“0” 求LIS,再把“0”都加回来。

  但,正如上面说的,可能存在“0”在两个连续自然数之间的情况。为了保证解的严格递增,我们可以将每个数的值减去它前面“0”的个数,这样ta就是纯的LIS了。

Code:

 

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
int _,n,Cnt,tot,A[100005],f[100005],Ans;
#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,65536,stdin),p1==p2)?EOF:*p1++)
char buf[65536],*p1,*p2;
inline int read()
{
    char ch;int x(0);
    while((ch=gc)<48);
    do x=x*10+ch-48;while((ch=gc)>=48);
    return x;
}
int main()
{
    _=read();
    for(register int __=1;__<=_;++__)
    {
        n=read(),Cnt=tot=0,memset(f,0x3f,sizeof f);
        for(register int i=0;i<n;++i)
        {
            A[Cnt]=read();
            if(!A[Cnt]) ++tot;
            else A[Cnt++]-=tot;
        }
        for(register int i=0;i<Cnt;++i) *lower_bound(f,f+n,A[i])=A[i];
        Ans=lower_bound(f,f+n,0x3f3f3f3f)-f;
        printf("Case #%d: %d\n",__,Ans+tot);
    }
    return 0;
}
View Code

 

posted @ 2021-07-19 18:45  qfxl  阅读(51)  评论(1)    收藏  举报