最大不降子序列

解法1(二分法:o(n*log2(n))):

#include <stdio.h>
#include <iostream>
#define MAXN 10000
using namespace std;

int a[MAXN], low[MAXN];

int main(void)
{
    int n;
    while(cin >> n)
    {
        low[1]=a[1];
        int now=1;
        for(int i=1; i<=n; i++)
        cin >> a[i];
        for(int i=2; i<=n; i++)
        {
            if(a[i]>low[now])  low[++now]=a[i];
            else
            {
                int pos=lower_bound(low, low+now, a[i]) - low;
                low[pos]=a[i];
            }
        }
        cout << now << endl;
    }
    return 0;
}

解法2(二分法队列实现:o(n*long2(n))):

#include <stdio.h>
#include <iostream>
#include <string.h>
#define MAXN 1000000
using namespace std;

int main(void)
{
    int n;
    while(cin >> n)
    {
        int stack[MAXN];
        int top=0;
        stack[0]=-1;
        for(int i=1; i<=n; i++)
        {
            int temp;
            cin >> temp;
            if(temp>stack[top])  stack[++top]=temp;
            else
            {
                int pos=lower_bound(stack, stack+top, temp)-stack;
                stack[pos]=temp;
            }
        }
        cout << top << endl;
    }
    return 0;
}

解法3(o(n*n)):

#include <stdio.h>
#include <iostream>
#define MAXN 10000+10
using namespace std;

int main(void)
{
    int n;
    while(cin >> n)
    {
        int a[MAXN], alen[MAXN], maxlen=1;
        for(int i=1; i<=n; i++)
        alen[i]=1;
        for(int i=1; i<=n; i++)
        cin >> a[i];
        for(int i=2; i<=n; i++)
        {
            int max=0;
            for(int j=1; j<=i-1; j++)
            if(a[j]<a[i] && max<alen[j])    max=alen[j];
            alen[i]=max+1;
            if(alen[i]>maxlen)   maxlen=alen[i];
        }
        cout << maxlen << endl;
    }
    return 0;
}

方法4(dp(o(n*n))):

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#define MAXN 100
using namespace std;

int main(void)
{
    int n;
    while(cin >> n)
    {
        int a[MAXN], low[MAXN];
        memset(low, 0, sizeof(low));
        for(int i=0; i<n; i++)
        cin >> a[i];
        for(int i=0; i<n; i++)
        {
            for(int j=i+1; j<n; j++)
            {
                if(a[j]>a[i])
                low[j]++;
            }

}
        sort(low, low+n);
        cout << low[n-1];
    }
    return 0;
}

时间: 2024-08-12 10:09:08

最大不降子序列的相关文章

动态规划-最长非降子序列

有关概念: 最长上升子序列(LIS,Longest Increasing Subsequence),在一个序列中最长的单调递增的子序列 思路: 求LIS通常有O(n2)和O(nlogn)两种算法 (1)O(n2)算法 fi表示以第i个数结尾的LIS长度 对于序列中的一个数i,在i前面枚举数j,j满足比i小且fj最大,将i作为j的后继 伪代码&状态转移方程: f1=1 for i=2...n for j=1...i-1 if(aj<ai)fi=max(fi,fj+1) 最后结果在f1~fn中取

最长不降子序列

最长不降子序列   原文http://www.cppblog.com/superKiki/archive/2010/08/09/122868.html 这题目是经典的DP题目,也可叫作LIS(Longest Increasing Subsequence)最长上升子序列或者 最长不下降子序列.很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) . 一.问题描述 设有由n个不相同的整数组成的数列,记为: a(1).a(2).--.a(n)且a(i)<>a(j) (i<&g

最长上升非降子序列的长度动态规划

第一种dp从后往前: dp[i]表示以a[i]为起点的最长上升非降子序列的长度 a[8]={10,2,2,4,12,23,34,2} dp[8]={4,6,5,4,3,2,1,1}; 代码实现: 1 #include<bits/stdc++.h> 2 using namespace std; 3 void logest_increase_sub(const int*a,int ssize) 4 { 5 int *dp=new int[ssize](); 6 int *p=new int[ssi

HDU 1025-Constructing Roads In JGShining&#39;s Kingdom(最长不降子序列,线段树优化)

分析: 最长不降子序列,n很大o(n^2)肯定超,想到了小明序列那个题用线段树维护前面的最大值即可 该题也可用二分搜索来做. 注意问题输出时的坑,路复数后加s #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vecto

poj 1631 最多能有多少条不交叉的线 最大非降子序列 (LIS)

左边的数字是1 2 3 4 5.... 右边的数字 第一个输入的和1连 第2个输入的和2连 右边再按从小到大排序 要求连线不能交叉 问最多能有多少条不交叉的线 假如右边有5个1 那么答案会是5 所以是最大非降子序列 Sample Input4 //T6 //n426315 Sample Output 3 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <al

BZOJ 1046 最长不降子序列(nlogn)

nlogn的做法就是记录了在这之前每个长度的序列的最后一项的位置,这个位置是该长度下最后一个数最小的位置.显然能够达到最优. BZOJ 1046中里要按照字典序输出序列,按照坐标的字典序,那么我萌可以把序列先倒着做最长下降子序列,然后我萌就可以知道以a[i]为开头的最长的长度了.每次扫一遍记录答案即可. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algori

【一维偏序】【最长上升子序列】【最长非降子序列】

两种方法,都是nlogn 树状数组型 #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int N=100003,M=50003; int d[N];//原数组 int f[M]; int n,big; int lowbit(int x) { return x&(-x); } //用于求上升序列 int

uvalive 6122 最长不降子序列

因为数据量非常小(n<=10),所以可以用dfs枚举每个长方体的状态,然后求LIS. 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int N = 10; 8 int dp[N]; 9 int n, ans; 10 11 struct T 12 { 13 int

[loj6088]可持久化最长不降子序列

考虑二分求LIS的过程,就是维护一个序列,其中第i个数表示长度为i的最小结尾,而插入操作就是查找第一个大于x的位置并替换掉 用线段树维护,二分的过程也可以用线段树来完成,对线段树可持久化即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define mid (l+r>>1) 5 int B,V,n,p,x,y,r[N],ans[N],f[N*30],ls[N*30],rs[N*30];