题目链接:猛戳这里
本题的关键是0的处理,0 是万能的数字,但不能重复,所以怎么好处理这个0非常关键。
于是一个思想就出来了,可不可以先不处理0,然后让a[i] 减去 i 之前 0 的个数。这样相对的大小不会改变,又 给 0 留下了位置。一举两得。
为什么可以?
举个栗子:1 0 2 0 3 0 3;
处理之后的序列为:1 1 1 0 (把 0 忽略,每一位非零 数字 - 0 的个数)
最长递增序列为 1 :
1 + 3(0的个数) = 4;
答案为四;
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <deque>
#include <map>
using namespace std;
typedef long long ll;
#define ForU(i,a,b) for(i = a;i < b;i ++)
#define ForD(i,a,b) for(i = a;i > b; i --)
#define Max 1000001
int number[Max];
int B[Max];
int len;
void revise(int l,int r,int under){
if(l == r){
if(B[l] > number[under])
B[l] = number[under];
return ;
}
else{
int mid = (l + r) >>1;
if(B[mid] >= number[under]){
revise(l,mid,under);
}
else{
revise(mid+1,r,under);
}
}
}
int main(){
int n,i,j,k,t;
scanf("%d",&t);
ForU(k,1,t+1){
scanf("%d",&n);
int sum = 0;
memset(number,0,sizeof(number));
ForU(i,0,n){
scanf("%d",&j);
if(j == 0){
sum ++;
}
else{
number[i-sum] = j - sum;
}
}
len = 0;
memset(B,0,sizeof(B));
ForU(i,0,n - sum){
if(len == 0 || number[i] > B[len-1]){
B[len ++] = number[i];
}
else{
revise(0,len -1,i);
}
}
printf("Case #%d: %d\n",k,len+sum);
}
return 0;
}
/****
2
7
2 0 2 1 2 0 5
6
1 2 3 3 0 0
10
10
8 6 2 3 9 5 2 0 1 5
*****/