• 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
  • 相关阅读:
    BZOJ4407
    BZOJ 4804
    BZOJ 2820
    莫比乌斯反演入门
    BZOJ3261
    BZOJ 4327
    BZOJ1212
    AC自动机 板子
    派生类的访问控制-“三看”原则-派生类类成员访问级别设置的原则
    为什么不要重载 && 和 || 操作符!!!
  • 原文地址:https://www.cnblogs.com/lcyhaha/p/6674116.html
Copyright © 2020-2023  润新知