uva-10534 Wavio Sequence

本文介绍了一种通过两次求解单调递增子序列的方法来找出序列中满足特定递增递减模式的最长特殊序列。首先从前往后求解一次单调递增子序列,再从后往前求解一次。通过比较每个位置上的两个子序列长度来确定最终答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接


题目大意

       从前往后n + 1个数都是递增的,然后从递增的最大一个值达到最后都是递减的也是n个数总共2*n+1个数。给你一个值求最长的一个满足上面要求的序列。

思路:

       从前往后求一次单调递增子序列,从后往前求一次单调递增子序列,每次记录下值然后记录最大值

代码:

#include<iostream>
#include<cstdio>
#include<map>
#include<math.h>
#include<cstring>
#include<algorithm>
#define INF 0x1f1f1f1f
using namespace std;
int main()
{
    int n, i, a[10010];
    while(scanf("%d",&n) != EOF)
    {
        for(i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
        }
        int t1 = 0, t2 = 0;
        int dp1[10010], s[10010], dp2[10010];
        memset(dp1, 0, sizeof(dp1));
        memset(s, -1, sizeof(s));
        int top = 0;
        s[0] = -INF;
        //从前往后求出单调递增子序列
        for(i = 1; i <= n; i++)
        {
            if(a[i] > s[top])
            {
                s[++top] = a[i];
                dp1[i] = top;
            }
            else
            {
                int l = 1, r = top;
                while(l <= r)
                {
                    int mid = (l + r) / 2;
                    if(a[i] > s[mid])
                    {
                        l = mid + 1;
                    }
                    else
                        r = mid - 1;
                }
                s[l] = a[i];
                dp1[i] = l;
            }
            if(dp1[i] > t1)
                t1 = dp1[i];
        }
        memset(dp2, 0, sizeof(dp2));
        memset(s, -1, sizeof(s));
        top = 0;
        s[0] = -INF;
        //从后往前求出单调递增子序列
        for(i = n; i > 0; i--)
        {
            if(a[i] > s[top])
            {
                s[++top] = a[i];
                dp2[i] = top;
            }
            else
            {
                int l = 1, r = top;
                while(l <= r)
                {
                    int mid = (l + r) / 2;
                    if(a[i] > s[mid])
                    {
                        l = mid + 1;
                    }
                    else
                        r = mid - 1;
                }
                s[l] = a[i];
                dp2[i] = l;
            }
            if(dp2[i] > t2)
                t2 = dp2[i];
        }
        int ans = 1,tem;
        //每次求最小值
        for(int i = 1;i <= n;i++)
        {
            tem = min(dp1[i],dp2[i]);
            ans = max(tem*2-1,ans);
        }
        cout << ans << endl;

    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值