P1216 (list加强版)

描述 Description
有N个整数,输出这N个整数的最长上升序列、最长下降序列、最长不上升序列和最长不下降序列。

 

输入格式 Input Format
第一行,仅有一个数N。 N<=700000
第二行,有N个整数。 -10^9<=每个数<=10^9

 

输出格式 Output Format
第一行,输出最长上升序列长度。
第二行,输出最长下降序列长度。
第三行,输出最长不上升序列长度。
第四行,输出最长不下降序列长度。

 

样例输入 Sample Input
10
1 3 0 8 6 2 3 1 4 2

 

样例输出 Sample Output


4

4

4

4

 

这道题因为数据量达到了700000,你要是写一个一般的DP绝对会超时的,所以就用二分查找来写,这道题虽然不是特别难,但却是分锻炼你的代码,而且还的注意一些细节

就是比方说有一个数组  6 5 4 3 2 1 1 1,那么你输出最长不上升序列长度就是8而不是6,最长不下降序列长度就是3而不是1.

血的教训:T.T(这道说练练快读吧,然后.....然后....MD少了2个等号,导致我一直不知道怎么错了,最后才发现数组不对,然后才AC)QAQ所以一定要细心

 

代码如下:

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<ctime>
#define maxn 710000
using namespace std;
int n;
int a[maxn],f1[maxn],g1[maxn];
int f2[maxn],g2[maxn];
int f3[maxn],g3[maxn];
int f4[maxn],g4[maxn];
inline int read()
{
    char ch=getchar();
    int x=0,f=1;
    while(ch>'9'||ch<'0')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int len;
int search1(int x)
{
    int left=0,right=len,mid;
    while(left+1<right)
    {
        mid=(left+right)/2;
        if(a[g1[mid]]<x)
            left=mid;
        else
            right=mid;
    }
    if(a[g1[right]]<x)
        left=right;
    return left;
}
void work1()//最长上升序列长度
{
    f1[1]=1;
    g1[1]=1;
    len=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>a[g1[len]])
        {
            len++;
            //cout<<a[i]<<' ';
            g1[len]=i;
            f1[i]=len;
        }
        else
        {
            int t=search1(a[i]);
            f1[i]=t+1;
            if(a[g1[t+1]]>a[i])
                g1[t+1]=i;
        }
    }
}
int search2(int x)
{
    int left=0,right=len,mid;
    while(left+1<right)
    {
        mid=(left+right)/2;
        if(a[g2[mid]]>x)
            left=mid;
        else
            right=mid;
    }
    if(a[g2[right]]>x)
        left=right;
    return left;
}
void work2()//最长下降序列长度
{
    f2[1]=1;
    g2[1]=1;
    len=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]<a[g2[len]])
        {
            len++;
            //cout<<a[g2[len]]<<' ';
            g2[len]=i;
            f2[i]=len;
        }
        else
        {
            int t=search2(a[i]);
            f2[i]=t+1;
            if(a[g2[t+1]]<a[i])
                g2[t+1]=i;
        }
    }
}
int search3(int x)
{
    int left=0,right=len,mid;
    while(left+1<right)
    {
        mid=(left+right)/2;
        if(a[g3[mid]]>=x)
            left=mid;
        else
            right=mid;
    }
    if(a[g3[right]]>=x)
        left=right;
    return left;
}
void work3()//最长不上升序列长度
{
    f3[1]=1;
    g3[1]=1;
    len=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]<=a[g3[len]])
        {
            len++;
            g3[len]=i;
            f3[i]=len;
        }
        else
        {
            int t=search3(a[i]);
            f3[i]=t+1;
            if(a[g3[t+1]]<=a[i])
                g3[t+1]=i;
        }
    }
}
int search4(int x)
{
    int left=0,right=len,mid;
    while(left+1<right)
    {
        mid=(left+right)/2;
        if(a[g4[mid]]<=x)
            left=mid;
        else
            right=mid;
    }
    if(a[g4[right]]<=x)
        left=right;
    return left;
}
void work4()//最长不下降序列长度
{
    f4[1]=1;
    g4[1]=1;
    len=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>=a[g4[len]])
        {
            len++;
            g4[len]=i;
            f4[i]=len;
        }
        else
        {
            int t=search4(a[i]);
            f4[i]=t+1;
            if(a[g4[t+1]]>=a[i])
                g4[t+1]=i;
        }
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        //cin>>a[i];
    }
    work1();
    cout<<len<<endl;
    work2();
    cout<<len<<endl;
    work3();
    cout<<len<<endl;
    work4();
    cout<<len<<endl;
    return 0;
}
View Code

 

posted @ 2017-04-06 16:30  列車員lcy  阅读(227)  评论(0编辑  收藏  举报