UVA 10534-Wavio Sequence(dp_正序逆序最长上升子序列)

Wavio Sequence

Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu

Submit Status

Description

Problem D

Wavio Sequence

Input: Standard Input

Output: Standard Output

Time Limit: 2 Seconds

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                                   Output for 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
           
9 
9 
1

 


Problemsetter: Md. Kamruzzaman, Member of Elite Problemsetters‘ Panel

Wavio是一个整数序列,具有以下特性:

1、Wavio序列的长度是奇数, 即 L = 2 * n + 1;

2、Wavio序列前 n+1 个整数是递增序列

3、Wavio序列后 n+1 个整数是递减序列

如示例 1 2 3 4 5 4 3 2 1 10

最长的 Wavio序列 为 1 2 3 4 5 4 3 2 1 ,所以答案为9

对于输入序列中的一个整数 ai ,我们设以 ai 为尾的前缀的最长递增序列的长度为Fi ,如在示例1中对已第3个整数3,从头开始,以3为尾的递增序列为1 2 3 ,所以F3=3;

以ai为首的后缀的递减序列的长度为Gi, 如示例1中第3个整数,以3为开始,递减序列为3 2 1,所以G3=3  (可以看做求从最后一个元素出发,到3这个位置的最大递增序列,为1 2 3,所以G3=3)

在我们找递减序列的时候,可以看做从最后一个元素出发,到当前位置的最大递增序列,这样我们对于每一个元素ai  我们可以先求出 a0到ai最大递增序列  和  an-1到ai的最大递增序列 ,这样我们可以得到ai的Wavio序列的值为

2*min( Fi , Gi) - 1 ,最后的结果是这些Wavio序列中的一个最大值。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>

using namespace std;
const int inf=0x3f3f3f3f;
int binsearch(int *a,int r,int key)
{
    int l=0;
    int mid=(l+r)/2;
    while(l<=r){
        if(a[mid]<key)
            l=mid+1;
        else if(a[mid]>key)
            r=mid-1;
        else
            return mid;
        mid=(l+r)/2;
    }
    return l;
}

int main()
{
    int n,i;
    while(~scanf("%d",&n)){
      int a[10010],b[10010],c[10010];//b保存的是以a[i]为结尾的最长递增子序列,c保存长度为i的递增子序列的最末的元素,c是单调递增的
      int a1[10010],b1[10010],c1[10010];//同上
      for(i=0;i<n;i++){
        scanf("%d",&a[i]);
        a1[n-i-1]=a[i];
      }
      for(i=0;i<n;i++)
        c[i]=inf;
      c[0]=-1;
      c[1]=a[0];//保存了长度为1时的递增序列的最末的元素,且此时长度为1的递增了序列只有一个,c[1]也是最小的;
      b[0]=1;//此时以a[0]结尾的最长递增子序列的长度为1.
      for(i=1;i<n;i++){
        int j=binsearch(c,n,a[i]);
        c[j]=a[i];
        b[i]=j;
      }
      for(i=0;i<n;i++)
        c1[i]=inf;
      c1[0]=-1;
      c1[1]=a1[0];
      b1[0]=1;
      for(i=1;i<n;i++){
        int j=binsearch(c1,n,a1[i]);
        c1[j]=a1[i];
        b1[i]=j;
      }
      int res=0;
      for(i=0;i<n;i++){
        res=max(res,min(b[i],b1[n-i-1]));
      }
      printf("%d\n",res*2-1);
    }
    return 0;
}
时间: 2024-12-21 06:46:44

UVA 10534-Wavio Sequence(dp_正序逆序最长上升子序列)的相关文章

LIS UVA 10534 Wavio Sequence

题目传送门 1 /* 2 LIS:应用,nlogn的做法,首先从前扫到尾,记录每个位置的最长上升子序列,从后扫到头同理. 3 因为是对称的,所以取较小值*2-1再取最大值 4 */ 5 /************************************************ 6 * Author :Running_Time 7 * Created Time :2015-8-5 21:38:32 8 * File Name :UVA_10534.cpp 9 ***************

uva 10534 Wavio Sequence LIS

// uva 10534 Wavio Sequence // // 可以将题目转化为经典的LIS. // 从左往右LIS记作d[i],从右往左LIS记作p[i]; // 则最后其中的min(d[i],p[i])就是这个波动序列的一半 // 在这最后的min(d[i],p[i]) * 2 + 1 的最大值就是我们所要求的答案 // // 这题开始想的最后的答案是d[i]==p[i]的时候求最大. // 但是这样是不对的,例如n=4, // 1,3,1,0 // 最长的应该是3,但是我的答案是1,明

UVa 10534 Wavio Sequence (最长递增子序列 DP 二分)

Wavio Sequence  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 s

UVa 10534 Wavio Sequence ( DP 二分 最长递增子序列 )

题意  求一个序列a某一位的最长递增序列(lis)和最长递减序列(lds)中最小值的最大值 开始直接用DP写了   然后就超时了  后来看到别人说要用二分把时间复杂度优化到O(n*logn)   果然如此   用一个栈s保存长度为i的LIS的最小尾部s[i]  top为栈顶即当前LIS的长度  初始s[1]=a[1]  top=1 遍历整个序列  当a[i]>s[top]时  a[i]入栈 in[i]=top   否则 在栈中查找(二分)第一个大于等于a[i]的下标pos  并替换  这样就增加

UVA 10534 Wavio Sequence(二分 + 最长上升子序列)

Wavio Sequence 题目: 题目大意: 题目是给一个序列,然后再其序列中找一个子序列,这个子序列符合前一半是递增的序列,后半部分是递减的序列,并且是这个序列中所有符合条件的子序列中最长的,输出其长度. 思路分析: 题目读懂以后,解法就迎刃而出了,很显然,正着求一个最长上升子序列,倒着求一个最长上升子序列.然后从这两个序列中找重合的位置最符合题意的,不过在这道题中,需要标记到每一位的最长上升子序列,因为每一位都可能成为符合题意的子序列的中间那一位置.这就需要用两个数组来标记,一个标记正方

UVA 10534 Wavio Sequence

题解: 根据最长上升子序列的nlog(n)做法,求出以每个点结尾的最长上升子序列. 然后反过来再求一次 然后取最小值 * 2 - 1 即可 代码: #include<bits/stdc++.h> using namespace std; #define pb push_back #define mp make_pair #define se second #define fs first #define lson l,m,rt<<1 #define rson m+1,r,rt<

C#数组的排序(正序逆序)

这种排序 超级简单的 ! using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication4 { class Program { static void Main(string[] args) { string[] str = { "d","h","a","c",&

Ka递归的编程练习 Part2|做到吐的正序逆序输出、等差数列和

1 #include<stdio.h> 2 void PP(int n) 3 { 4 if(n==0) return; 5 PP(n/10); 6 printf("%d",n%10); 7 } 8 void NP(int n) 9 { 10 if(n==0) return; 11 printf("%d",n%10); 12 PP(n/10); 13 } 14 int Ad(int n) 15 { 16 if(n==0) return 0; 17 if(n

正序逆序生成单链表

typedef struct LNode{ int key; struct LNode *next; }LNode,*List; //正序生成单链表 void CreateList1(List &L,int n){ L=(List)malloc(sizeof(LNode)); L->next=NULL; LNode *q=L; for(int i=1;i<=n;i++) { LNode *p=(LNode *)malloc(sizeof(LNode)); scanf("%d&