lightoj 1421 Wavio Sequence (最长严格单峰子序列)

177 篇文章 0 订阅
77 篇文章 8 订阅
Wavio Sequence
Time Limit: 4 second(s)     Memory Limit: 32 MB

Wavio is a sequence of integers. It has some interesting properties:
1.      Wavio is of odd length i.e. L = 2*n + 1.
2.      The first (n+1) integers of Wavio sequence make a strictly increasing sequence.
3.      The last (n+1) integers of Wavio sequence make a strictly decreasing sequence.
4.      No two adjacent integers are same in a Wavio sequence.
For example 1, 2, 3, 4, 5, 4, 3, 2, 1 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 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

Input starts with an integer T (≤ 12), denoting the number of test cases.

Each case starts with a line containing an integer N (1 ≤ N ≤ 105) denoting the number of elements in the sequence. The next line contains N space separated integers between -108 to 108, that form the sequence.


Output

For each case, print the case number and the length of the maximum possible Wavio sequence.

Sample Input

3
10
1 2 3 4 5 4 3 2 1 10
14
1 2 3 2 1 2 3 4 3 2 1 5 4 1
5
1 2 3 4 5
    
Output for Sample Input
Case 1: 9
Case 2: 7

Case 3: 1


题目链接:http://lightoj.com/volume_showproblem.php?problem=1421

题目大意:求最长的严格单峰子序列,单峰就是先增后减,严格就是相邻的数字不等,子序列就是选的数字不要求连续

题目分析:从左到右,从右到左分别求一次最长上升子序列,求的时候用nlogn的解法记录到当前数字所能组成的上升子序列的最大长度,比如第i个点左到右记录的为ldp[i],右到左记录的为rdp[i],答案就是2 *min(ldp[i], rdp[i]) - 1,减1是因为中间那个数字重复了一次

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 1e5 + 5;
int n, a[MAX];
int lstk[MAX], rstk[MAX];
int ldp[MAX], rdp[MAX];
int ltop, rtop;

int main() {
    int T;
    scanf("%d", &T);
    for(int ca = 1; ca <= T; ca ++) {
        printf("Case %d: ", ca);
        scanf("%d", &n);
        for(int i = 0; i < n; i ++) {
            scanf("%d", &a[i]);
        }
        ltop = rtop = 0;
        for(int i = 0; i < n; i ++) {
            ldp[i] = 1;
            if(ltop == 0 || lstk[ltop - 1] < a[i]) {
                lstk[ltop ++] = a[i];
            }
            else {
                int pos = lower_bound(lstk, lstk + ltop, a[i]) - lstk;
                lstk[pos] = a[i];
            }
            ldp[i] = ltop;
        }
        for(int i = n - 1; i >= 0; i --) {
            rdp[i] = 1;
            if(rtop == 0 || rstk[rtop - 1] < a[i]) {
                rstk[rtop ++] = a[i];
            }
            else {
                int pos = lower_bound(rstk, rstk + rtop, a[i]) - rstk;
                rstk[pos] = a[i];
            }
            rdp[i] = rtop;
        }
        int ans = 1;
        for(int i = 0; i < n; i ++) {
            ans = max(ans, 2 * (min(rdp[i], ldp[i])) - 1);
        }
        printf("%d\n", ans);
    }
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值