O(nlogn)的最长上升子序列并且记录所选择的数 模板

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 10000 + 10;
int A[MAXN];
int lis[MAXN];
int f[MAXN];
int stack[MAXN];
int N;
int main()
{
    while(scanf("%d", &N)!=EOF)
    {
        for(int i=1;i<=N;i++)
            scanf("%d", &A[i]);
        int top = 1;
        stack[1] = A[1];
        f[1] = 1;
        for(int i=2;i<=N;i++)
        {
            if(A[i] > stack[top])
            {
                stack[++top] = A[i];
                f[i] = top;
            }
            else
            {
                int pos = lower_bound(stack, stack + top, A[i]) - stack;
                stack[pos] = A[i];
                f[i] = pos;
            }
        }
        cout << top << endl;
        int t = top;
        for(int i=N;i>=1;i--)
        {
            if(f[i] == t)
            {
                lis[--t] = i;
            }
            if(t < 0) break;
        }
        for(int i=0;i<top;i++)
         cout << lis[i] << ' ';
        cout << endl;
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-24 12:51:17

O(nlogn)的最长上升子序列并且记录所选择的数 模板的相关文章

nlogn 求最长上升子序列 LIS

最近在做单调队列,发现了最长上升子序列O(nlogn)的求法也有利用单调队列的思想. 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更好的方法. 考虑两个数a[x]和a[y],x&

HDU-1025 Constructing Roads In JGShining&#39;s Kingdom O(nlogn)的最长上升子序列

模板题,唯一问题是当长度为1是,road是单数,不然road是复数roads. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <queue> #include <vector> #include <cstdlib> #include <algorithm> using namespace st

(最长上升子序列 并记录过程)FatMouse&#39;s Speed -- hdu -- 1160

http://acm.hdu.edu.cn/showproblem.php?pid=1160 FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 12338    Accepted Submission(s): 5405Special Judge Problem Description FatMouse be

HDU4604.Deque——nlogn求最长上升子序列的长度

http://acm.hdu.edu.cn/showproblem.php?pid=4604 把一个序列中的元素放到队列里面,有3种操作,对于第i个元素 1.放到队头2.放到队尾3.舍弃 求最长上升序列的长度 法1:求出每个以a[i]为起点的最长不升子序列的长度,和最长不降子序列的长度,两个相加再减去a[i]重复的次数 法2:把当前序列复制两个,一个逆序,求总共的最长上升子序列的长度,然后奇偶避免重复 //法1 #include <iostream> #include <cstring&

CSU 1225 最长上升子序列并记录其个数

1 for(int j=0;j<i;j++){ 2 if(h[i] > h[j]){ 3 if(len[i] == len[j] + 1) cnt[i]+=cnt[j]; 4 if(len[i] < len[j] + 1) len[i] = len[j] + 1 , cnt[i] = cnt[j]; 5 } 6 //身高相同的情况统计 7 /*else if(h[i] == h[j]){ 8 if(len[i] == len[j]) cnt[i] += cnt[j]; 9 if(len[

最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现

关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已经做了实现,但是这种方法时间复杂度太高,查阅相关资料后我发现有人提出的算法可以将时间复杂度降低为O(nlogn),这种算法的核心思想就是替换(二分法替换),以下为我对这中算法的理解: 假设随机生成的一个具有10个元素的数组arrayIn[1-10]如[2, 3, 3, 4, 7, 3, 1, 6,

最长上升子序列 O(nlogn)解法 (转)

转自 http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更

最长上升子序列算法(n^2 及 nlogn) (LIS)

问题描述: 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N.比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等.这些子序列中最长的长度是4,比如子序列(1, 3, 5

最长上升子序列(LIS)长度的O(nlogn)算法

最长上升子序列(LIS)的典型变形,熟悉的n^2的动归会超时.LIS问题可以优化为nlogn的算法.定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素.注意d中元素是单调递增的,下面要用到这个性质.首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],则根据D的定义,我们需