题意是:
给你一个长度为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;
}