lightoj 1421 - Wavio Sequence LIS变形

来源:互联网 发布:知乎电脑版下载官网 编辑:程序博客网 时间:2024/06/06 23:30

题目求一个长度为奇数的序列,然后这个序列里面前半部分升序后半部分降序,中间那个值是最大的,求最大长度。

首先序列可以拆分成一个升序,一个降序序列,然后因为中间值在两个序列中都有,所以就是中间点是可以O(n)枚举的,我们要求的就是以i为中点的情况下长度最长,也就是以i为终点的最长上升子序列和以i 为起点的最长下降子序列,因为要求两端序列长度相等,所以答案就是其中的最小值*2-1。

LIS有nlogn求法,应付10W刚好

#include<bits/stdc++.h>using namespace std;#define N 101000int num1[N],num2[N];int ans[N],q[N],h[N];int erfen(int s[],int l,int r,int x){    int mid,ans=-1;    while(l<=r)    {        mid=(l+r)/2;        if(s[mid]>=x)        {            r=mid-1;            ans=mid;        }        else        {            l=mid+1;        }    }    return ans;}int main(){    int t;    scanf("%d",&t);    for(int cas=1;cas<=t;cas++)    {        int n,len;        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%d",&num1[i]);            num2[n-i+1]=num1[i];        }        memset(ans,0,sizeof(ans));        memset(q,0,sizeof(q));        ans[1]=num1[1];        len=1;        q[1]=1;        for(int i=2;i<=n;i++)        {            if(num1[i]>ans[len])            {                ans[++len]=num1[i];                q[i]=len;            }            else            {                int pos=erfen(ans,1,len,num1[i]);                ans[pos]=num1[i];                q[i]=pos;            }        }        memset(h,0,sizeof(h));        memset(ans,0,sizeof(ans));        ans[1]=num2[1];        len=1;h[n]=1;        for(int i=2;i<=n;i++)        {            if(num2[i]>ans[len])            {                ans[++len]=num2[i];                h[n-i+1]=len;            }            else            {                int pos=erfen(ans,1,len,num2[i]);                ans[pos]=num2[i];                h[n-i+1]=pos;            }        }        int answer=1;        for(int i=1;i<=n;i++)        {            int tmp=min(q[i],h[i]);            answer=max(answer,tmp*2-1);        }        printf("Case %d: %d\n",cas,answer);    }    return 0;}


0 0
原创粉丝点击