NYOJ 823 人形序列

来源:互联网 发布:淘宝店分析 编辑:程序博客网 时间:2024/05/01 23:00

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;}


0 0
原创粉丝点击