#include <iostream>]
using namespace std;
int dp[100005];
//1.大于目前dp数组的最后一个元素,那么显然我们应该将它加入到dp数组中,数组长度加1
//2.小于等于,那么这个元素也不是一无是处,我们就用它来更新dp数组的值,我们找到第一
// 个比他大的数,那么长度为该数下标的最长上升子序列末尾的最小值就是这个新元素啦!
int a[100005];
int n;
int ans = 0;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
{
if (a[i] > dp[ans])
{
ans++;
dp[ans] = a[i];
}
else
{
for (int j = 1; j <= ans; j++)
{
if (dp[j] > a[i])
{
dp[j] = a[i];
break;
} //↓改成二分查找
}
}
}
cout << n - ans;
return 0;
}
可改为二分查找
#include <bits/stdc++.h>
using namespace std;
const int N=100001;
int a[N],dp[N];
//dp[i]表示从最长上升子序列i时第i个位置的最小值
int n,ans=0;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
if(a[i]>dp[ans])
{
ans++;
dp[ans]=a[i];
}
else
{
//二分优化
int l=1,r=ans,mid;
while(l<r)
{
mid=(l+r)/2;
if(a[i]<=dp[mid])//在mid的左边
{
r=mid;//右边更新为mid,因为mid有可能是答案,所以不能写成了mid-1
}
else //if(a[i]>=dp[mid])
{
l=mid+1;//左边更新为mid,因为mid不可能是答案,所以mid+1
}
}
dp[l]=a[i];
}
}
cout<<n-ans<<endl;
return 0;
}