Poj 1631 n*logn 的最长上升子序列(LIS)算法

来源:互联网 发布:sql查询例题 编辑:程序博客网 时间:2024/05/18 13:07

这里找到题目

题意是找出让连线不交错的最大剩余线的个数

一看题就知道是求最长上升子序列
但是,看看数据范围就知道,很明显普通的LIS算法会超时
这个时候,我们就要优化。

多创建一个d数组和int len 变量,d[len] 表示长度为len的上升子序列的最后一个元素,如果读入一个数,它的值为x,有d[i] < x < d[i+1]的话,我们就把d[i+1] 赋值为 x,当然,如果i+1>len的话,len++。
利用d数组的单调性我们可以轻松用log n的复杂度找到 上面的那个i
最后算出的len就是答案。

下面贴代码

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <cmath>using namespace std;const int maxn = 40010;//int a[maxn];一开始我还想保存所有读入的数,事实证明我想多了,没必要int d[maxn];int main(){    int t;    scanf("%d",&t);    while(t--){        int p,x;        scanf("%d",&p);        scanf("%d",&x);        int len = 1;        d[len] = x;        for(int i=1;i<p;i++){            scanf("%d",&x);            int t = lower_bound(d+1,d+len+1,x) - (d+1);            //printf("%d t\n",t);            if(t==len){                len++;                d[len] = x;            }else {                d[t+1] = x;            }        }        printf("%d\n",len);    }    return 0 ;}

如果觉得我讲的不好,请参考最长上升子序列(LIS)n*log n 算法

0 0