HDU 5773 The All-purpose Zero 第四场多校赛 LIS变形(最长上升子序列)

来源:互联网 发布:阿里云ecs sn型号 编辑:程序博客网 时间:2024/05/19 03:25

点击打开链接

题意是:

给你一个长度为10W的数组,每个数范围0-100W

其中的0可以变为INT范围内的任意值

问最长上升子序列的长度

思路:

0可以转化成任意整数,包括负数,

显然求LIS时尽量把0都放进去必定是正确的。

因此我们可以把0拿出来,对剩下的做O(nlogn)的LIS,

统计结果 的时候再算上0的数量。


(因为本来是应该使dp[len+1]=dp[len]+1,并且其他的值也会相应的改变,但是这样不好算, 所以我们就倒着来)

为了保证严格递增,

我们可以将每个权值S[i]减去i前面0的个数,

再做LIS,就能保证结果是严格递增的

#include<iostream>#include<cstring>#include<map>#include<cstdio>#include<cmath>#include<queue>#include<algorithm>#include<stack>#define mod 19999#define INF 0x3f3f3f3f#define bug  puts("***********")using namespace std;int dp[1000000];int main(){    int n,m,t,x,cas=0;    scanf("%d",&t);    int num=0;    while(t--){        int cnt=0,num=0;        dp[0]=-INF;  ///会出现 000000000000000 1 的情况 所以必须将 a[0] 变成最小值        scanf("%d",&n);        for(int i=0;i<n;i++){            scanf("%d",&x);            if(!x) num++;            else {                 x=x-num;               if(dp[cnt]<x){                 dp[++cnt]=x;                }               else{                 int pos=lower_bound(dp+1,dp+cnt+1,x)-dp;                 if(dp[pos]>x){                    dp[pos]=x;                 }              }           }        }        printf("Case #%d: %d\n",++cas,cnt+num);    }    return 0;}


0 0
原创粉丝点击