HDU 5773 The All-purpose Zero 16多校4 贪心 LCA

来源:互联网 发布:网站源码加密破解 编辑:程序博客网 时间:2024/04/29 12:27
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5773

题意:给一个有n(n<=100000)个数字的序列,其中要么是0要么是正整数,0可以变成任意整数,问该序列的最长上升子序列。
比赛的时候被这题卡了三个小时,貌似因为数据水,有的人错误的代码都过了,自己真的菜啊…………

思路:贪心的思路应该是基于这个结论:lca不一定包含所有0,但是所有0组成的某个序列一定是lca其中的一个。大题证明思路:如果有一个lca不含所有的0,那么我们可以把这个lca中靠近原序列中的0的某个数换成0,数次这样操作,这个lca就变成了包含所有0的lca。

那么正如题解说的,可以把所有的0拿出来,每个非0的数减去前面出现的0的个数,然后对这些数计算lca,加上0的总数就ok了,这样得到的lca包含了所有0,且保证了其他非0数组成的lca最长

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<cstdlib>using namespace std;#define MS(x,y) memset(x,y,sizeof(x))#define MP(x,y) make_pair(x,y)#define lowbit(x) (x&(-x))typedef long long LL;inline void fre1(){freopen("1010.in","r",stdin);/*freopen("output.txt","w",stdout);*/}inline void fre2(){fclose(stdin);/*fclose(stdout);*/}const int MAXN=100000+5;const double EPS=1e-8;int n,x,tot,sum;int a[MAXN],dp[MAXN];int main(){    int T,kase=0;    scanf("%d",&T);    while(T--){        bool flag=false;        scanf("%d",&n);        tot=0,sum=0;        for(int i=1;i<=n;++i){            scanf("%d",&x);            if(x) a[++tot]=x-sum,flag=true;            else ++sum;        }        MS(dp,0);        dp[1]=a[1];        int ans=1;        for(int i=2;i<=tot;++i){            int p=lower_bound(dp+1,dp+1+ans,a[i])-dp;            dp[p]=a[i];            ans=max(ans,p);        }        if(!flag) ans=0;        printf("Case #%d: %d\n",++kase,ans+sum);    }    return 0;}


0 0