UVA10534:Wavio Sequence(最长递增和递减序列 n*logn)(LIS)好题

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68553#problem/B

 题目要求:

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

题目解析:

    这题做了一中午,第一次做完之后果断TLE了,第一次的做法是对于序列(1,n)暴力求解,先求出a[i]的最长子序列,再求以a[i]为开始的最长递减序列,注意求递增递减

的二分的边界写法。这时候遍历一遍max(min(a[i]的最长,a[i]的最短)*2-1),即为所求结果,不幸直接TLE了。

之后一想,可以先求出这个序列的最长子序列,并记录每一个数最长子序列。

同理,再倒序求出序列的最长子序列,并记录每一个数最长子序列。

这时候在遍历一遍每个数,结果即为max(min(a[i]的最长增长子序列,a[i]的最长递减子序列)*2-1);理由不言而喻。

   A了一中午,值得纪念。

AC的:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
int n,a[10002],d[10002],w[10002],ad[10002],ad2[10002],sum,len,l2;
int er(int q[],int l,int r,int key)//好好研究二分
{
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(q[mid]==key)
        {
            return mid;
        }
        else if(q[mid]>key)
        {
            r=mid-1;
        }
        else l=mid+1;
    }
    return l;
}
int main()
{
    int we;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
        }
        sum=1;
        len=1;
        d[len]=a[1];
        ad[1]=1;
        for(int i=2; i<=n; i++)
        {
            if(a[i]>d[len])
            {
                d[++len]=a[i];
                ad[i]=len;
            }
            else
            {
                we=er(d,1,len,a[i]);
                d[we]=a[i];
                ad[i]=we;
            }
        }
        l2=1;
        w[l2]=a[n];
        ad2[n]=1;
        for(int i=n-1; i>=1; i--)
        {
            if(a[i]>w[l2])
            {
                w[++l2]=a[i];
                ad2[i]=l2;
            }
            else
            {
                we=er(w,1,l2,a[i]);
                w[we]=a[i];
                ad2[i]=we;
            }
        }
        for(int i=1;i<=n;i++)
        {
            sum=max(sum,(min(ad[i],ad2[i])*2-1));
        }
        printf("%d
",sum);
    }
    return 0;
}

TLE的:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
int n,a[10002],d[10002],w[10002],sum,len,l2;
int er(int q[],int l,int r,int key)//好好研究二分
{
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(q[mid]==key)
        {
            return mid;
        }
        else if(q[mid]>key)
        {
            r=mid-1;
        }
        else l=mid+1;
    }
    return l;
}
int er2(int q[],int l,int r,int key)//好好研究二分
{
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(q[mid]==key)
        {
            return mid;
        }
        else if(q[mid]>key)
        {
            l=mid+1;
        }
        else r=mid-1;
    }
    return l;
}
int main()
{
    int we,wei;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
        }
        sum=1;
        len=1;
        d[len]=a[1];
        for(int i=2; i<=n; i++)
        {
            if(a[i]>d[len])
            {
                d[++len]=a[i];
                l2=1;
                w[l2]=a[i];
                for(int j=i+1; j<=n; j++)
                {
                    if(a[j]<w[l2])
                    {
                        w[++l2]=a[j];
                        if(l2==len)
                        {
                            break;
                        }
                    }
                    else
                    {
                        wei=er2(w,1,l2,a[j]);
                        w[wei]=a[j];
                    }
                }
                if(l2<=len) sum=max(sum,(2*l2-1));
                 //printf("sum==%d
",sum);
            }
            else
            {
                we=er(d,1,len,a[i]);
                d[we]=a[i];
                if(len<=1) continue;
                l2=1;
                w[l2]=a[i];
                for(int j=i+1; j<=n; j++)
                {
                    if(a[j]<w[l2])
                    {
                        w[++l2]=a[j];
                        if(l2==we)
                        {
                            break;
                        }
                    }
                    else
                    {
                        wei=er2(w,1,l2,a[j]);
                        w[wei]=a[j];
                    }
                }
                if(l2<=we)  sum=max(sum,(2*l2-1));
                 //printf("sum==%d
",sum);
            }
        }
        printf("%d
",sum);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhangmingcheng/p/4263091.html