pku 1631

这道题是最长上升序列。
由于给出的数据量过大,不能直接使用dp的方法来去最长升序,因为这样的时间为0(n^2)  
下面我们考虑如下的情况:
对于第i个数来说他是否是1……i的最长上升序列的元素,就是在1……i-1中的最长上升序列最后一个值比f[i]小,那么f[i]元素就为1……i上的最长上升序列的元素。
如过不存在1……i-1的最长上升序列满足上述情况时,我们不能直接认为i就1……n上的最长升序列。这是我们可以这样的假设,假设f[i]是1……n的最长生序列的元素。那么f[i]在1……n的最长升序列的位置应该在1……i-1的最长生序列中比f[i]小的最大的元素之后的位置k。当在i+1……n比x-k(x为1……i-1的最长上升序列的长度)大的时候,假设就成立。如果更新位置k上的值为f[i],最长上升序列的长度会变。
DP source code(TLE):
 #include<iostream>
#include<algorithm>
int a[40001],dp[40001];
using namespace std;
int main()
{
    int n,p,i,j,k,Max;
    cin>>n;
    while(n--)
        {
          cin>>p;
          Max=-1;
          memset(a,0,sizeof(a));
          memset(dp,0,sizeof(dp));
          for(i=1;i<=p;i++)
            {
              scanf("%d",&a[i]);//cin>>a[i];            
            }
            for(j=1;j<=p;j++)
            {
              dp[j]=1;
              for(k=1;k<i;k++)
                {                 
                  if(a[j]>a[k])
                    dp[j]=max(dp[j],dp[k]+1);         
                }
                if(dp[j]>Max)
                Max=dp[j];
              }
              cout<<Max<<endl;
        }
        return 0;
}
二分source code
#include<iostream>
#include<algorithm>
int c[40001];
int k;
using namespace std;
int Check(int p)
{
    if(c[k-1]<p)  c[k++]=p;
    else
    {
      int left=0,right=k-1;
      while(left!=right)
          {
            int mid=(left+right)/2;
            if(c[mid]<p)
            left=mid+1;
            else
            right=mid;           
          }
          c[left]=p; 
    }
    return -1;
}
int main()
{
    int n,p;
    cin>>n;
    while(n--)
        {
          cin>>p;
          k=1;
          memset(c,0,sizeof(c));
          for(int i=1;i<=p;i++)
            {
               int a;
               scanf("%d",&a);  //cin>>a;   454ms
               Check(a); 
            }  
            cout<<k-1<<endl;
        }
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值