P1410 子序列

题目描述

给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列,

输入输出格式

输入格式:

 

若干行,每行表示一组数据。对于每组数据,首先输入一个整数N,表示序列的长度。之后N个整数表示这个序列。

 

输出格式:

 

同输入行数。对于每组数据,如果存在一种划分,则输出“Yes!”,否则输出“No!“。

 

输入输出样例

输入样例#1: 复制
6 3 1 4 5 8 7
6 3 2 1 6 5 4
输出样例#1: 复制
Yes!
No!

说明

【数据范围】

共三组数据,每组数据行数<=50,0 <= 输入的所有数 <= 10^9

第一组(30%):N <= 20

第二组(30%):N <= 100

第三组(40%):N <= 2000

 

//。。这道题。。。。我竟然不会做
//如果一个序列中的不升子序列长度>2了,那么这个序列一定就不能被分成2个lis了
//一定是>2个lis
//emmmm   ----> 最长不升子序列长度就是最大最长上升子序列的个数。 <----
//所以,如果一个序列能被分成两个长度相等的lis,那么最长不升子序列长度一定<=2
//如果==2的话,正好可以分成两个,否则原序列是个完全单调上升序列,把它怎么拆都能拆成两个长度相等的lis 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;

const int N=2005;

int n;
int a[N];
int dp[N];
int lis[N],len;

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;++i)
            scanf("%d",a+i);
        lis[len=1]=a[1];
        bool flag=0;
        for(int i=2;i<=n;++i)
        {
            if(a[i]>lis[len])
            {
                int pos=lower_bound(lis+1,lis+len+1,a[i],greater<int>() )-lis;        //lower_bound()真好用啊 
                if(pos==len+1)
                    lis[1]=a[i];
                //cout<<pos<<" ";
                else lis[pos]=a[i];
            }
            else
                lis[++len]=a[i];
            if(len>2)
            {
                flag=1;
                break;
            }
        }
        if(flag)
            puts("No!");
        else
            puts("Yes!");
    }
    return 0;
}

 

posted @ 2018-02-27 08:57  whymhe  阅读(154)  评论(0编辑  收藏  举报