洛谷 P1410 子序列

来源:互联网 发布:js指定日期格式化 编辑:程序博客网 时间:2024/06/16 03:15

这题乍一看毫无思路。显然不可能穷举长度为N/2的严格递增子序列。

不过联想到NOIP1999(普及组)的导弹拦截的第二问,就有思路了。这题其实与它的第二问差不多,只要算出该序列的最大非升子序列长度L,判断一下是否大于2即可。

1.假如L>2,显然一个严格递增子序列至多包含非升子序列的一个元素,2个子序列至多包含2个元素,故两个严格递增子序列不可能把原序列的每个元素都包含,所以输出No!

2.假如L<=2:

2.1若L=1,显然原序列严格递增,必能按照题意划分,输出Yes!

2.2若L=2,用反证法易得去除一个长度为2的非升子序列之后的序列严格递增。

因此,将这两个元素分别放到两个子序列里面,总能构造出两个严格递增的子序列。


【分析】
orz题解,真的好强呜呜哇哇
[题解 by courage]

这题乍一看毫无思路。显然不可能穷举长度为N/2的严格递增子序列。

不过联想到NOIP1999(普及组)的导弹拦截的第二问,就有思路了。这题其实与它的第二问差不多,只要算出该序列的最大非升子序列长度L,判断一下是否大于2即可。

1.假如L>2,显然一个严格递增子序列至多包含非升子序列的一个元素,2个子序列至多包含2个元素,故两个严格递增子序列不可能把原序列的每个元素都包含,所以输出No!

2.假如L<=2:

2.1若L=1,显然原序列严格递增,必能按照题意划分,输出Yes!

2.2若L=2,用反证法易得去除一个长度为2的非升子序列之后的序列严格递增。

因此,将这两个元素分别放到两个子序列里面,总能构造出两个严格递增的子序列。


【代码】

#include<iostream>#include<cstdio>#include<cstring>#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;int a[2005],dp[2005],n;int main(){    while(scanf("%d",&n)==1)    {        memset(dp,0,sizeof dp);        int ans=0,i,j;        fo(i,1,n) scanf("%d",&a[i]),dp[i]=1;        fo(i,1,n)        {            fo(j,1,i-1)            {                if(a[i]<=a[j])                  dp[i]=max(dp[i],dp[j]+1);            }            ans=max(ans,dp[i]);        }        if(ans<=2) printf("Yes!\n");        else printf("No!\n");    }    return 0;} 
1 0
原创粉丝点击