POJ3903 Stock Exchange

  • 题目大意:求最长上升子序列……
  • 思路:看这数据规模,L<=100000,还一个点多组测试数据,O(n2)的是不用指望了,于是要使用O(nlogn)的算法。
  • 说一下该算法:令序列存于数组a中在O(n2)的算法中,我们对于一个f[i]值的确定,需要扫描j=1->i-1的所有a[j]值,并取a[j]<a[i]时的f[j]的最大值。试想如果存在两个个值x与y,满足x<y<i,x<y,且f[x]=f[y],在构建序列的过程中,我们应该选择x还是y?显然,应该是x,因为在a[x]至a[i]中可能存在一个可以用于构建序列的元素。对于任意的满足f[t]=某一值k的所有a[t],我们记d[k]=min(a[t]),即表示从1至某一位置最长上升子序列长度为k的末尾元素值的最小值,于是可以发现,对于序列d,有d[1]<d[2]<…<d[k-1]<d[k],因为我们保存的都是最小元素值,每增加序列长度,放在最后的元素,因为是上升子序列,必然比原先的末尾元素大。于是我们得出这样一个策略,对于已经求出的长度为len(注意,是已经求出)的序列,对于某个元素a[t],如果a[t]>d[len],只需令a[t]接在d[len]之后,然后len++,即此时序列长度得到增加;否则,在序列d中寻找满足a[t]>d[j]的最大的j,令d[j+1]=a[t],但是因为序列长度没有增加,所以对len无操作。实际操作时,只需枚举序列中的每一个元素,这是O(n)的,在寻找元素插入位置时,由于d具有单调性,我们可以利用二分查找,这是O(logn)的。于是,总时间复杂度降至O(nlogn)。
  • 代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
const int maxl=100005;
int l,a[maxl],c[maxl];

int find(int l,int r,int x)
{
    int mid=(l+r)/2;
    if (l==r)
      return l;
    if (c[mid]>x)
      return find(l,mid,x);
    else
      return find(mid+1,r,x);
}

void work()
{
    int len=0,j;
    c[1]=-10000;
    for (int i=1;i<=l;++i)
    {
        if (a[i]>c[len])
          j=++len;
        else j=find(1,len,a[i]);
        c[j]=a[i];
    }
    printf("%d\n",len);
}

void init()
{
    while (scanf("%d",&l)==1)
    {
        for (int i=1;i<=l;++i)
          scanf("%d",&a[i]);
        work();
    }
}

int main()
{
    init();
    return 0;
}

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

时间: 2024-12-21 14:10:58

POJ3903 Stock Exchange的相关文章

poj3903 Stock Exchange最大上升子序列

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://poj.org/problem?id=3903 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 about the ev

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

poj3903 Stock Exchange 二分+dp

题目地址:http://poj.org/problem?id=3903 题目: 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 about the evolution of the stock exchange. He fo

poj3903 Stock Exchange(最长上升子序列)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:id=3903">http://poj.org/problem?id=3903 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

POJ3903:Stock Exchange(LIS)

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 about the evolution of the stock exchange. He follows stock prices every day looking for

POJ 3903 Stock Exchange

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 about the evolution of the stock exchange. He follows stock prices every day looking for rising tren

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

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