题意:一个非负序列里 0可以变成包括负数在内的任何数 问这个序列的最长严格上升子序列有多长
官方给的题解:0可以转化成任意整数,包括负数,显然求LIS时尽量把0都放进去必定是正确的。因此我们可以把0拿出来,对剩下的做O(nlogn)的LIS,统计结果的时候再算上0的数量。为了保证严格递增,我们可以将每个权值S[i]减去i前面0的个数,再做LIS,就能保证结果是严格递增的。
条件一:这个最长的上升子序列一定包含了原始序列中的全部0
证明:假设一个某个上升子序列不完全包含全部的0,这样我们可以将没有被包含的0加入这个序列中,由于0可以变为任何数,所以新序列的长度一定大于等于原序列的长度
题解没看懂……但是照着题解写 还是AC了
代码:
#include <cstdio>
#include <iostream>
#define sf scanf
#define pf printf
using namespace std;
const int maxn = 100000 + 5;
int num[maxn];
int g[maxn];
int main(){
int T,ca = 0;
sf("%d",&T);
while( T-- ){
int n;
sf("%d",&n);
int pre_zero = 0,num_size = 0;
for(int i = 0;i < n;++i){
int temp;
sf("%d",&temp);
if(!temp) pre_zero++;
else{
num[num_size++] = temp - pre_zero;
}
}
int ans = 0;
if(!num_size){
ans = 0;
}else{
ans = 1;
g[1] = num[0];
for(int i = 1;i < num_size;++i){
if(num[i] > g[ans]){
g[++ans] = num[i];
}
else{
int k = lower_bound(g + 1,g + ans + 1,num[i]) - g;
g[k] = num[i];
}
}
}
pf("Case #%d: %d\n",++ca,ans + pre_zero);
}
return 0;
}