现在的位置: 首页 > 综合 > 正文

NYOJ 823 人形序列

2017年11月23日 ⁄ 综合 ⁄ 共 1105字 ⁄ 字号 评论关闭

http://acm.nyist.net/JudgeOnline/problem.php?pid=823

http://ayit.acmclub.com/index.php?app=problem_title&id=233&problem_id=21812

对于序列中的每一个元素都要进行预处理。

例如:                          原序列:1 2 3 4 5 4 3 2 1 10

处理以后得到两个新序列:s:1 2 3 4 5 4 3 2 1 10

                                                 t::1 2 3 4 5 4 3 2 1 1

其中s  序列式对于原序列中的每一个元素对应正向的单增子序列的长度,t 序列对应原序列中的每一个元素对应逆向的单增子序列的长度。

对于人形序列,我们要求中间的元素 最大,向两个方向依次减小,并且左右 两边的长度相等。

所以我们可以枚举中间的元素,例如,对于 10 而言,从左往右的子序列长度为10 ,从右往做的子序列的长度为1,所以以 10 为中间元素的子序列的长度应该为3,。

对于原序列中第 二次 出现元素 4 的情况,他对应的子序列的长度应该跟 第一次出现的 4 是一样的。所以我们应该在已经形成的序列中找到第一个 大于4的元素的位子。为了避免因为数组初始化照成找不到的问题,要把数组初始化成 最大的值。 这里用到一个函数   fill (dp , dp + n , inf )。
在一个有序的序列中查找第一个大于等于某一个元素的位子,可以用lower _bound()。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf = 0x7fffffff;
int a[10010],s[10010],t[10010],dp[10010];
int main()
{
    int n;
    while(cin>>n && n)
    {
        int i;
        for(i = 0; i < n; i++)
        cin>>a[i];

        fill(dp,dp + n,inf);
        for(i = 0; i < n; i++)
        {
            int id = lower_bound(dp,dp+n,a[i]) - dp;
            dp[id] = a[i];
            s[i] = id+1;
        }

        fill(dp,dp + n, inf);
        for(i = n-1; i >= 0; i--)
        {
            int id = lower_bound(dp,dp+n,a[i]) - dp;
            dp[id] = a[i];
            t[i] = id+1;
        }
        int maxx = 0;
        for(i = 0; i < n; i++)
        {
            maxx = max(maxx,(min(s[i],t[i])<<1) -1);
        }
        cout<<maxx<<endl;
    }
    return 0;
}
【上篇】
【下篇】

抱歉!评论已关闭.