POJ 3903 Stock Exchange (LIS:最长上升子序列)

POJ 3903Stock Exchange (LIS:最长上升子序列)

http://poj.org/problem?id=3903

题意:

给你一个长度为n (n<=100000) 的数字序列, 要你求该序列中的最长(严格)上升子序列的长度.

分析:

由于n的规模达到10W, 所以只能用O(nlogn)的算法求.

令g[i]==x表示当前遍历到的长度为i的所有最长上升子序列中的最小序列末尾值为x.(如果到目前为止,
根本不存在长i的上升序列,
那么x==INF无穷大)

假设当前遍历到了第j个值即a[j], 那么先找到g[n]数组的值a[j]的下确界(即第一个>=a[j]值的g[k]的k值).
那么此时表明存在长度为k-1的最长上升子序列且该序列末尾的位置<j且该序列末尾值<a[j].

那么我们可以令g[k]=a[j] 且 dp[i]=k (dp含义如解法1).

(上面一段花时间仔细理解)

最终我们可以找出下标最大的i使得: g[i]<INF 中i下标最大. 这个i就是LIS的长.

AC代码: O(n*logn)复杂度

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100000+5;
const int INF=1e8;

int n;
int a[maxn];
int dp[maxn];
int g[maxn];

int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);

        for(int i=1;i<=n;i++)
            g[i]=INF;

        int ans=0;
        for(int i=1;i<=n;i++)
        {
            int k=lower_bound(g+1,g+n+1,a[i])-g;
            dp[i]=k;
            g[k]=a[i];
            ans=max(ans,k);
        }

        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-15 02:41:17

POJ 3903 Stock Exchange (LIS:最长上升子序列)的相关文章

poj 3903 Stock Exchange(最长上升子序列,模版题)

题目 #include<stdio.h> //最长上升子序列 nlogn //入口参数:数组名+数组长度,类型不限,结构体类型可以通过重载运算符实现 //数组下标从1号开始. int bsearch(int a[],int len,int num) { int left=1,right=len; while(left<=right) { int mid=(left+right)/2; if(num<=a[mid]) //若最长不下降子序列,改<= 为 < right=m

{POJ}{3903}{Stock Exchange}{nlogn 最长上升子序列}

题意:求最长上升子序列,n=100000 思路:O(N^2)铁定超时啊....利用贪心的思想去找答案.利用栈,每次输入数据检查栈,二分查找替换掉最小比他大的数据,这样得到的栈就是更优的.这个题目确实不错,思路很好 #include <iostream> #include <string> #include <cstring> #include <cstdio> #include <algorithm> #include <memory>

POJ 3903 Stock Exchange 【最长上升子序列】模板题

题目链接:http://poj.org/problem?id=3903 转载于:https://www.cnblogs.com/GodA/p/5180560.html 题目大意: 裸的DP最长上升子序列,给你一段序列,求其最长上升子序列的长度,n^2的dp朴素算法过不了,这里用的是nlogn的算法,用了二分查找. 具体算法思路解析: 学习动态规划问题(DP问题)中,其中有一个知识点叫最长上升子序列(longest  increasing subsequence),也可以叫最长非降序子序列,简称L

POJ 3903 Stock Exchange LIS

题目链接:http://poj.org/problem?id=3903 题目大意:LIS的nlog(n)写法. 解题思路:dp[i]:=长度为i的最长递增子序列的末尾元素最小值.那么由于dp[i]形成了一个有序的序列,所以可以采用二分的办法. dp[j] = a[i]  dp[j] <= a[j] < dp[j + 1] 代码: 1 const int inf = 0x3f3f3f3f; 2 const int maxn = 1e5 + 5; 3 int a[maxn], n; 4 int d

POJ3903 Stock Exchange LIS最长上升子序列

POJ3903 Stock Exchange 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 1e5+5; 7 int a[maxn]; 8 int main() { 9 int n; 10 while (~scanf("%d",&am

LIS(nlogn) POJ 3903 Stock Exchange

题目传送门 1 /* 2 最长递增子序列O(nlogn)算法: 3 设当前最长递增子序列为len,考虑元素a[i]; 4 若d[len]<a[i],则len++,并将d[len]=a[i]; 5 否则,在d[1~len]中二分查找,找到第一个比它小的元素d[j],并d[j]=a[i]. 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #include <iostream> 10 #include <algori

POJ - 3903 Stock Exchange(LIS最长上升子序列问题)

E - LIS Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description The world financial crisis is quite a subject. Some people are more relaxed while others are quite anxious. John is one of them. He is very concerned abo

POJ 1887 Testingthe CATCHER (LIS:最长下降子序列)

POJ 1887Testingthe CATCHER (LIS:最长下降子序列) http://poj.org/problem?id=3903 题意: 给你一个长度为n (n<=200000) 的数字序列, 要你求该序列中的最长(严格)下降子序列的长度. 分析:        读取全部输入, 将原始数组逆向, 然后求最长严格上升子序列就可以. 因为n的规模达到20W, 所以仅仅能用O(nlogn)的算法求.        令g[i]==x表示当前遍历到的长度为i的全部最长上升子序列中的最小序列末

POJ 3903 Stock Exchange(LIS)

Stock Exchange Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4578   Accepted: 1618 Description The world financial crisis is quite a subject. Some people are more relaxed while others are quite anxious. John is one of them. He is very