您的位置:首页 > 其它

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

2016-08-01 09:40 337 查看
点击打开链接

题意是:

给你一个长度为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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: