最长上升子序列

8

1 2 5 7 3 4 6 8

复杂度 o(n^2)

#include<bits/stdc++.h>
using namespace std;
int a[100];
int dp[100];
int32_t main()
{
    int n; cin>>n;
    for(int i=1;i<=n;i++) { cin>>a[i]; dp[i]=1;}
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<i;j++)
        {
            if(a[i]>a[j])
            {
                dp[i]=max(dp[i],dp[j]+1);
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
    cout<<ans<<endl;
}

优化; o(nlogn)  

方法一 二分+贪心

最长上升子序列 贪心+二分
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int a[100];
int low[100];
int32_t main()
{
    int n; cin>>n;
    for(int i=1;i<=n;i++)  { cin>>a[i]; low[i]=INF;}
    low[1]=a[1];   int ans=1;
    for(int i=2;i<=n;i++)
    {
        if(low[ans]<a[i])
        {
            low[++ans]=a[i];
        }
        else
        {
            int k=lower_bound(low+1,low+ans,a[i])-low;
            low[k]=a[i];
        }
    }
  //  for(int i=1;i<=ans;i++)  cout<<low[i]<<"   ";  cout<<endl;
    cout<<ans<<endl;
}
lower_bound 写的简介代码

   用low_lound的情况少    一般题目不会让你直接用low_bound;

方法二   dp+ 树状数组;

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int n;
int T[maxn];
struct person
{
    int val;
    int num;
}node[maxn];
bool comp(person a,person b)
{
    if(a.val!=b.val) return a.val<b.val;
    return a.num<b.num;
}
void modify(int x,int y)  //把val[x]替换为val[x]和y中较大的数
{
    for(;x<=n;x+=x&(-x)) T[x]=max(T[x],y);
}
int query(int x) //返回val[1]~val[x]中的最大值
{
    int res=-INF;
    for(;x;x-=x&(-x)) res=max(res,T[x]);
    return res;
}
int32_t main()
{
     cin>>n;
    for(int i=1;i<=n;i++) { cin>>node[i].val; node[i].num=i;}
    sort(node+1,node+1+n,comp);
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int t=query(node[i].num);
        modify(node[i].num,++t);
        ans=max(ans,t);
    }
    cout<<ans<<endl; return 0;
}
dp+树状数组

洛古p1091 

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+5;
int n;
int a[maxn];
int row[maxn];
int low[maxn];
int divid(int x)
{
    memset(low,0,sizeof(low));
    memset(row,0,sizeof(row));
    int ans1=1;
    low[ans1]=a[x];
    for(int i=x-1;i>=1;i--)
    {
        if(a[i]<low[ans1])
        {
            low[++ans1]=a[i];
        }
        else if(a[i]>=a[x]) continue;
        else if(a[i]==low[ans1]) continue;
        else if(a[i]>low[ans1] && a[i]<a[x] )
        {
            for(int j=1;j<ans1;j++)//  o(n^2);
            {
                if(low[j]>a[i]&&a[i]>=low[j+1])
                {
                    low[j+1]=a[i];
                    break;
                }
            }
        }
    }
    int ans2=1;
    row[ans2]=a[x];
    for(int i=x+1;i<=n;i++)
    {
       // cout<<ans2<<endl
        if(a[i]<row[ans2])
        {
            row[++ans2]=a[i];
        }
        else if(a[i]>=a[x]) continue;
        else if(a[i]==row[ans2]) continue;
        else
        {
            //cout<<a[i]<<endl;
            for(int j=1;j<ans2;j++)
            {
                if(row[j]>a[i]&&a[i]>=row[j+1])
                {
                    row[j+1]=a[i];
                }
            }
        }
    }
   // cout<<"   "<<ans1<<"   "<<ans2<<endl;
   // for(int i=1;i<=ans1;i++) cout<<low[i]<<"   "; cout<<endl;
   // for(int i=1;i<=ans2;i++) cout<<row[i]<<"   "; cout<<endl;
    int ans=ans1+ans2;
    return ans;
}
int32_t main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int maxlong=0;
    for(int i=1;i<=n;i++)
    {
        int k=divid(i);
        k=k-1;
        //cout<<k<<endl;
        maxlong=max(k,maxlong);
    }
    cout<<n-maxlong<<endl;
}
p1091
原文地址:https://www.cnblogs.com/Andromeda-Galaxy/p/9460173.html