UVA 10534 LCS变种题

求一个序列中 的2*n-1个数字 ,前n+1个数字为严格升序 后n+1个为严格降序,求最长的长度

一开始还没想清楚怎么解,其实就是一个LCS问题,从头到尾以及反序求一下LCS

由于 d[i]为包含了自身的LCS,所以每次比较 min(d1[i],d2[i]),再 2*min-1即可,d1和d2分别为正序和反序的LCS。

由于时间卡的紧,要用之前学过的压栈法求LCS,时间复杂度为n*logn,中间出了一些问题,首先就是保存每个节点的LCS值的时候,如果该点是大于sta[top],那自然LCS为top+1,但是如果不是的话,我一开始写成top,原来不是,是要二分的那个位置才是。。。。还有就是二分一开始调用的是Upper_bound,错了,应该是lower_bound

再复习下 upper_bound是找大于val的第一个位置点,如果val小于整个序列,返回 0,如果val大于整个序列,返回数组的最后一位+1。

lower_bound是找大于并等于val的第一个值,如果序列中没有==val的,那跟upper是一样的效果,如果有相同的,并且同时有几个相同的,则返回第一个相同的数的下标。上界和下界是跟upper一样的。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define N 10010
using namespace std;
int d1[N],d2[N],A[N];
int n,sta[N];
void init()
{
    int top=0;
    sta[0]=-1;
    sta[++top]=A[1];
    d1[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (A[i]>sta[top]){
            sta[++top]=A[i];
            d1[i]=top;
        }
        else
        {
            int loc=lower_bound(sta+1,sta+top+1,A[i])-sta;
            sta[loc]=A[i];
            d1[i]=loc;
        }

    }
    top=0;
    sta[++top]=A[n];
    d2[n]=1;
    for (int i=n-1;i>=1;i--)
    {
        if (A[i]>sta[top]){
           sta[++top]=A[i];
           d2[i]=top;
        }
        else
        {
            int loc=lower_bound(sta+1,sta+top+1,A[i])-sta;
            sta[loc]=A[i];
            d2[i]=loc;
        }

    }
}
void test()
{
    for (int i=1;i<=n;i++)
    {
        printf("%d %d\n",d1[i],d2[i]);
    }
}
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&A[i]);
        }
        init();
        //test();
        int ans=0;
        for (int i=1;i<=n;i++)
        {
            int tmp=min(d1[i],d2[i]);
            ans=max(ans,2*tmp-1);
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/kkrisen/p/3614446.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值