最长上升子序列 两种写法

二 贪心 O nlogn;

解题思路
利用贪心 + 二分查找的思想。维护一个数组 q,其中 q[i] 表示长度为 i + 1 的最长上升子序列的末尾元素的最小值。
遍历数列:对输入数列中的每个元素 a[i] 进行处理。
二分查找:在 q 数组中通过二分查找找到第一个大于等于 a[i] 的位置。如果找到的位置 r 对应的 q[r] 大于 a[i],说明可以用 a[i] 替换 q[r],使得长度为 r + 1 的上升子序列末尾元素更小,更有利于后续构造更长的上升子序列;如果 r 等于当前记录的最长上升子序列长度 len,则说明找到了一个更长的上升子序列,len 自增。
更新数组:将 a[i] 赋值给 q[r],完成对 q 数组的更新。
获取结果:遍历完整个数列后,len 的值就是最长上升子序列的长度。

#include<bits/stdc++.h>

using namespace std;
const int N=100100;
int n;
int a[N];
int q[N];//距离为len的

int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    q[0]=-2e9;
    
    int len=0;
    for(int i=0;i<n;i++)
    {
        int l=0,r=len;
        while(l<r)
        {
            int mid=l+r+1>>1;
            if(q[mid]<a[i])
            {
                l=mid;
            }
            else  r=mid-1;
        }
    //    cout<<r<<endl;
        
        len=max(len,r+1);
        q[r+1]=a[i];
       // cout<<len<<" "<<q[len]<<endl;
    }
    cout<<len;
    return  0;
}

// 最长上升子序列 第二种写法
int q[N] // 序列
int g[N] // 记录最长的最后一个值
int cnt=0;
for(int i=0;i<n;i++)
{
  int k=0;
  while(k<cnt && g[k]<q[i]) k++;
  g[k]=q[i];
  if(k>=cnt) cnt++;
}
cout<<cnt;

最长拦截系统

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int N=1e5+10; // 修正数组大小
int f[N], q[N], a[N], cnt=0;

void solve()
{
    // 输入数据,以 EOF 结束(按 Ctrl+Z 或 Ctrl+D)
    while(cin>>a[++cnt]);
    cnt--; // 去掉最后的无效数据

    // 计算最长非递增子序列(LNDS)
    int len=0;
    f[0] = INT_MAX; // 初始化哨兵
    for(int i=1; i<=cnt; i++)
    {
        int l=0, r=len;
        while(l < r)
        {
            int mid = (l + r + 1) >> 1;
            if(f[mid] >= a[i]) l = mid;
            else r = mid - 1;
        }
        len = max(len, r + 1);
        f[r + 1] = a[i];
    }
    cout << len << "\n"; // 换行

    // 计算最长递增子序列(LIS)
    len=0;
    q[0] = INT_MIN; // 初始化哨兵
    for(int i=1; i<=cnt; i++)
    {
        int l=0, r=len;
        while(l < r)
        {
            int mid = (l + r + 1) >> 1;
            if(q[mid] < a[i]) l = mid;
            else r = mid - 1;
        }
        len = max(len, r + 1);
        q[r + 1] = a[i];
    }
    cout << len << "\n"; // 换行
}

int main()
{
    ios;
    int _=1;
    while(_--)
    {
        solve();
    }
    return 0;
}
posted on 2025-03-28 14:09  下头小美  阅读(44)  评论(0)    收藏  举报