#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+7;
#define ll long long
int a[maxn];
int dp_1[maxn];///LIS
int dp_2[maxn];///最长非上升子序列
int n=0;
int main()
{
int x;
while(scanf("%d",&x)!=EOF)
{
a[++n]=x;
}
int ans_1=0;
int ans_2=0;
memset(dp_1,0,sizeof (dp_1));
memset(dp_2,0,sizeof (dp_2));
for (int i=1;i<=n;++i)
{
dp_1[i]=1;
for (int j=1;j<i;++j)///找寻之前的是否可以合并
{
if (a[i]>a[j])
{
ans_1 = max(ans_1,dp_1[i]=max(dp_1[i],dp_1[j]+1));
}
}
ans_1=max(ans_1,dp_1[i]);///判断是否加入原来的子序列,否则直接以a[i]单独创建一个子序列
}
for (int i=n;i>=1;--i)///仔细理解后就会发现就是反向跑一遍lis
{
dp_2[i]=1;
for (int j=i+1;j<=n;++j)
{
if (a[i]>=a[j])///记得加上等于
{
ans_2 = max(ans_2,dp_2[i]=max(dp_2[i],dp_2[j]+1));
}
}
ans_2=max(ans_2,dp_2[i]);
}
printf("%d\n%d\n",ans_2,ans_1);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+7;
const int INF=0x3f3f3f3f;
#define ll long long
int B[maxn];///入队LIS数组
int A[maxn];///原数组
int C[maxn];///最长非上升子序列数组
int n=0;
int A_search(int r,int x){///>
int mid,l=1;
while (l<=r){
mid=(l-r)/2+r;
if (B[mid]<x)
{
l=mid+1;
}
else
{
r=mid-1;
}
}
return l;///最后满足就是刚好小于
}
int B_search(int r,int x){///>=
int mid,l=1;
while (l<=r){
mid=(l-r)/2+r;
if (C[mid]<=x)
{
l=mid+1;
}
else
{
r=mid-1;
}
}
return l;
}
int main()
{
while(EOF!=scanf("%d",&A[++n])){
}--n;
int lis=1;
B[1]=A[1];
for (int i=2;i<=n;++i){
if (A[i]>B[lis]){///如果当前比入队的最大值还大就直接入队
B[++lis]=A[i];
}
else {
int t= A_search(lis,A[i]);///找到第一个大于等于A[i]的元素位置
B[t]=A[i];///替换
}
}
int ans=1;
C[1]=A[n];///倒序
for (int i=n-1;i>=1;--i){///反向查询
if (A[i]>=C[ans]){///如果当前比入队的最大值还大或者等于就直接入队
C[++ans]=A[i];
}
else {///由于等于的也可以入队,所以查找时直接就查找大于的位置
int t= B_search(ans,A[i]);///找到第一个大于A[i]的元素位置
C[t]=A[i];///替换
// cout<<t<<endl;
}
}
printf("%d\n%d\n",ans,lis);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+7;
const int INF=0x3f3f3f3f;
#define ll long long
int n=0;
int a[maxn];///储存原数组
int b[maxn];///储存长度
int c[maxn];///储存当前最小子数组LIS
int d[maxn];///储存长度
int f[maxn];///储存当前最小子数组,非上升子序列
int main()
{
while (scanf("%d",&a[n])!=EOF)
{
++n;
}
fill(c,c+n,INF);
fill(d,d+n,INF);///由于是要直接得到位置,则最后超过实际的查询长度遇到INF就截止了
int maxx_1=-INF;
for (int i=0;i<n;++i)
{
int j=lower_bound(c,c+n,a[i])-c;///减去本身得到位置
b[i]=j+1;
maxx_1=max(b[i],maxx_1);
c[j]=a[i];///直接取代
}
int maxx_2=-INF;
for (int i=n-1;i>=0;--i)
{
int j=upper_bound(d,d+n,a[i])-d;///由于等于号也算进去,此时只要找到最大位置即可
f[i]=j+1;
maxx_2=max(f[i],maxx_2);
d[j]=a[i];
}
printf("%d\n%d\n",maxx_2,maxx_1);
return 0;
}
原文:https://www.cnblogs.com/qimang-311/p/13396449.html