[UVa 10534]Wavio Sequence

该博客讨论了如何找到给定序列中最长的Wavio子序列,即奇数长度且前半部分递增、后半部分递减的子序列。作者提出了将问题转化为LIS(最长递增子序列)问题的解决方案,并描述了如何通过从左右两端分别计算LIS长度来求解。博客包含了示例输入、输出,以及作者的问题报告和源代码。

Problem Description

Wavio is a sequence of integers. It has some interesting properties.
• Wavio is of odd length i.e. L = 2 ∗ n + 1.
• The first (n + 1) integers of Wavio sequence makes a strictly increasing sequence.
• The last (n + 1) integers of Wavio sequence makes a strictly decreasing sequence.
• No two adjacent integers are same in a Wavio sequence.
For example 1, 2, 3, 4, 5, 4, 3, 2, 0 is an Wavio sequence of length 9. But 1, 2, 3, 4, 5, 4, 3, 2, 2 is
not a valid wavio sequence. In this problem, you will be given a sequence of integers. You have to find
out the length of the longest Wavio sequence which is a subsequence of the given sequence. Consider,
the given sequence as :

1 2 3 2 1 2 3 4 3 2 1 5 4 1 2 3 2 2 1

Here the longest Wavio sequence is : 1 2 3 4 5 4 3 2 1. So, the output will be ‘9’.

Input

The input file contains less than 75 test cases. The description of each test case is given below. Input
is terminated by end of file.
Each set starts with a postive integer, N (1 ≤ N ≤ 10000). In next few lines there will be N
integers.

Output

For each set of input print the length of longest wavio sequence in a line.

Sample Input

10
1 2 3 4 5 4 3 2 1 10
19
1 2 3 2 1 2 3 4 3 2 1 5 4 1 2 3 2 2 1
5
1 2 3 4 5

Sample Output

9
9
1

My Problem Report

这是一道比较简单的LIS拓展,只需在LIS算法中加入一个数组标记以原序列每个元素为结尾的LIS长度,并从左向右,从右向左分别做一次LIS。
这道题的Trick在于,虽然题面要求长度为n*2+1的序列,但其实左右两部分可以不相等,每次取Min(leftlen,rightlen)*2+1即可。

My Source Code

//  Created by Chlerry in 2015.
//  Copyright (c) 2015 Chlerry. All rights reserved.
//

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
using namespace std;
#define Size 10010
#define ll long long
#define mk make_pair
#define pb push_back
#define mem(array, x) memset(array,x,sizeof(array))
typedef pair<int,int> P;

int a[Size],l[Size],r[Size],cnt1[Size],cnt2[Size];
int main()
{
    int n;
while(cin>>n && n)
{
    for(int i=1;i<=Size;i++)
         l[i]=r[i]=INT_MAX;
    for(int i=0;i<n;i++)
        cin>>a[i];
    l[1]=a[0];cnt1[0]=1;
    for(int i=1;i<n;i++)
    {
        int pos=lower_bound(l,l+n+1,a[i])-l;
        l[pos]=a[i];
        cnt1[i]=pos;
    }
    r[1]=a[n-1];cnt2[n-1]=1;
    for(int i=n-2;i>=0;i--)
    {
        int pos=lower_bound(r,r+n+1,a[i])-r;
        r[pos]=a[i];
        cnt2[i]=pos;
    }   
    int maxn=1; 
    for(int i=0;i<n;i++)
        if(cnt1[i]>1 && cnt2[i]>1)//cnt1[i]==cnt2[i] && 
            maxn=max(maxn,min(cnt1[i],cnt2[i])*2-1);
    cout<<maxn<<endl;
}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值