HDU5773 The All-purpose Zero
题意
- HDU5773多校训练2016第四场1010题
- 求一串数的LIS,0可以变为任意数
题解
多校第四轮,引用自官方解答
0可以转化成任意整数,包括负数,显然求LIS时尽量把0都放进去必定是正确的。因此我们可以把0拿出来,对剩下的做O(nlogn)的LIS,统计结果的时候再算上0的数量。为了保证严格递增,我们可以将每个权值S[i]减去i前面0的个数,再做LIS,就能保证结果是严格递增的。
刚好复习LIS的O(nlogn)求法,本质上就是,维护当前最长序列,当新数比末尾数更大,加入序列末尾,序列增长,如果小于,那么更新序列中可插入位置的数,保证后续能取得更优解。
例如:
12**4**5
->12**3**5
代码
#include <cstdio>
#define MAX 100000
#define INF 1000000
int a[MAX], c[MAX], len;
int find(int L,int R,int x)
{
if(L==R) return L;
int mid=(L+R)>>1;
if(c[mid]<x) return find(mid+1,len,x);
else return find(L,mid,x);
}
int main()
{
int i,cas,n,t,m,T,b,k,ans,j,max,zero;
scanf("%d",&T);
for(cas=1;cas<=T;++cas)
{
scanf("%d",&n);
zero=0;
for(i=0,m=0;i<n;i++)
{
scanf("%d",&a[i]);
if(a[i] == 0)
++zero;
else
a[m++] = a[i] - zero;
}
len=0; c[0]=-INF;
for(i=0;i<m;i++)
{
if(a[i]>c[len]) j=++len;
else j=find(1,len,a[i]);
c[j]=a[i];
}
printf("Case #%d: %d\n", cas,len+zero);
}
}