思路:建立一个cnt数组用来存可能放置 的元素,然后对于s数组的每一位,
如果s[i]大于cnt的最大值,那么可以直接加入,即,
如果不大于的话,那么我们就要看能不能加入这个元素,但是如果加入的话,会把比他大的所有的元素清空,那么我们就假设将他加入cnt中(交换的位置是大于等于s[i]的第一个元素),但是cnt的长度不发生变化。这样子可以使我们的cnt的递增的长度不变,同时在后面的遍历中可以得到最长的长度。
样例:1 4 6 3 4 5 首先前三个元素可以正常加入cnt中,轮到第四个元素时加入到4的位置,表面上没有任何影响,但是对于3和4来说,3之后可以加入的元素的可能性是大于4的(前提是之后得有一个4),就相当于a和b(a>b),如果我们把b加入进去了,那么a-b的数都可能会被我们加入进去,当然如果没有范围是a-b加入进去也无所谓,因为这是一种可能的状态。
,比如 1 2 6 8 5 ,答案是1 2 5 8,但是cnt中存的是1 2 5 8,这个5 是为了之后能加入更多元素而服务的。
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100;
int n ,m;
ll s[N];
ll cnt[N];
int main()
{
int t=0;
cin>>n;
memset(cnt,-0x3f3f3f3f,sizeof cnt);
for(int i=1;i<=n;i++)
cin>>s[i];
for(int i=1;i<=n;i++)
{
if(s[i]>cnt[t])
cnt[++t]=s[i];
else {
int l=1 ,r=t,mid;
while(r>l)
{
mid=l+r>>1;
if(cnt[mid]>=s[i])r=mid;//记住可以等于
else l=mid+1;
}
swap(cnt[r],s[i]);
}
}
cout<<t<<endl;
return 0;
}