HDU1950[Bridging signals] LIS模型 (nlogn)

来源:互联网 发布:乐视手机移动网络设置 编辑:程序博客网 时间:2024/06/08 00:44

最长上升子序列(LIS) nlogn方法


a[]数组存原序列

ans[] 第i位 表示 长度为 i 的 上升子序列的结尾 最小为 ans[i]

a[]={4,2,6,3,1,5} len为最长上升子序列长度

模拟过程:

先 ans[1]=a[1]. ans={4} len=1

a[2]=2, 2 小于 ans[len] ,即 2 < 4 , 所以 2可以替换4。 ans={2}, len=1

a[3]=6, 6 大于 ans[len] , 即 6 > 2, 所以6可以加入上升序列 ans[++len]=6, ans={2,6}, len=2

a[4]=3, 3<6并且 3>2,显然,应该用3替换2 所以 ans[len]=3, ans={2,3} len=2

a[5]=1, 1<2 所以 1 替换 2, ans[1]=1, ans={1,3} len=2

a[6]=5, 5>3 所以 5 加入序列 ans[++len]=5, ans={1,3,5}, len=3

最长上升子序列长度为3

算法流程:

定义 原数组 a, 答案数组 b
枚举 a 数组中的每个元素
如果大于b的最后一个元素
当前元素加入 b
答案长度+1
否则
二分查找 a当前元素 替换 b 中的位置
替换 b 中 的 元素


题目链接


题意:求给出序列的最长上升子序列

#include <cstdio>#include <vector>#include <iostream>#include <algorithm>using namespace std;vector<int> a, ans;vector<int>::iterator t; int main(){    int n, T;    scanf("%d", &T );    while( T-- ){        a.clear(); ans.clear();        scanf("%d", &n );        for ( int i=1, x=0; i<=n; i++ ) scanf("%d", &x ), a.push_back(x);        ans.push_back(a[0]);        for ( int i=1; i<a.size(); i++ ){            if( a[i]>ans[ans.size()-1] ) ans.push_back(a[i]);            else {                t=lower_bound(ans.begin(), ans.end(),a[i]);                *t=a[i];            }        }        printf("%d\n", ans.size() );    }}