[原]POJ-1631-Bridging signals-( 水LIS-O(nlogn) -DP)

题目大意:求最长上升子序列(LIS)长度,序列最大数不超过40000。因为只有上升排列的接口才不相交。


思路:普通的 O(n^2)的做法肯定会超时;因此,dp[ ] 记录长度为 i+1 的子序列中最末元素的最小值,这一数组是单调递增的,因此对于dp[ ]数组内元素可以用二分搜索找出dp[ ]中比 a[ i ] 大的最小的元素的位置;这里用到了STL类里的 lower_bound(x, x+n, k)函数(http://www.cplusplus.com/reference/algorithm/lower_bound/?kw=lower_bound)函数返回排好序的序列 x[ ] 中满足 x[ i ]  >= k  的 x[ i ] 的最小指针。


AC代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define M 40010
#define INF 1000000
int dp[M],a[M];
void init(int *a, int n)
{
  for(int i = 0; i < n; i++)
  {
    a[i] = INF;
  }
}

int main()
{
  int n;
  scanf("%d",&n) == 1;
  while(n--)
  {
    int x;
    scanf("%d",&x);
    for(int i = 0; i < x; i++)
      scanf("%d",&a[i]);
    init(dp,x);
    for(int i = 0; i < x; i++)
      *lower_bound(dp, dp+x, a[i]) = a[i];
    cout<<lower_bound(dp, dp+x, INF) - dp<<endl;
  }
  return 0;
}


作者:u011652573 发表于2014-3-6 14:58:03 原文链接
阅读:51 评论:0 查看评论
原文地址:https://www.cnblogs.com/ZiningTang/p/3834757.html