• TYVJ P1067 合唱队形 Label:上升子序列?


    背景

    NOIP2004 提高组 第三道

    描述

        N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。

        合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,  则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K)。

        你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

    输入格式

       输入文件chorus.in的第一行是一个整数N(2<=N<=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130<=Ti<=230)是第i位同学的身高(厘米)。

    输出格式

        输出文件chorus.out包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

    测试样例1

    输入


    186 186 150 200 160 130 197 220

    输出

    4

    备注

    对于50%的数据,保证有n<=20;
    对于全部的数据,保证有n<=100。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define INF 1<<30
    using namespace std;
    int N,res=INF,a[105],b[105],dp[105],f[105],l,r;
    int longest(int k){
        fill(dp,dp+N,INF);
        for(int i=1;i<=k;i++){
            *lower_bound(dp,dp+N,a[i])=a[i];
            if(i==k) l=lower_bound(dp,dp+N,INF)-dp;
        }
    //    printf("k=%d l=%d ",k,l);
        fill(dp,dp+N,INF);
        for(int i=1;i<=N-k+1;i++){
            *lower_bound(dp,dp+N,b[i])=b[i];
            if(i==N-k+1) r=lower_bound(dp,dp+N,INF)-dp;
        }
    //    printf("r=%d
    ",r);
        if(r==1||l==1) return -1;
        return l+r-1;
    }
    int main(){
    //    freopen("01.txt","r",stdin);
        scanf("%d",&N);
        for(int i=1;i<=N;i++) scanf("%d",&a[i]);
        for(int i=1;i<=N;i++) b[i]=a[N-i+1];
    //    for(int i=1;i<=N;i++) printf("%d ",b[i]);
        
        for(int i=1;i<=N;i++){
            int k=longest(i);
            if(k==-1) k=INF;
            else k=N-k;
            res=min(res,k);
        }
        
        if(res==INF) res=0;
        printf("%d
    ",res);
        return 0;
    }

    直接顺序读入a数组,再逆序复制一份到b,枚举中间点,过一下最长上升子序列,

    记录当中间点推入时的序列长度,得到最小值;

    其实可以不用逆序复制,为了不浪费时间,采用了O(nlogn)的lower_bound;

    看了下题解发现本来就是上升或下降(即没有答案时)要输出0

    非二分做法如下

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #define inf 0x3f3f3f3f
     6 using namespace std;
     7 int a[10005],zuo[10005],you[10005],N;
     8 int zuo_(){
     9     fill(zuo,zuo+10000,1);
    10     for(int i=1;i<=N;i++){
    11         for(int j=i+1;j<=N;j++){
    12             if(a[j]>a[i]) zuo[j]=max(zuo[j],zuo[i]+1);
    13         }
    14     }
    15 }
    16 int you_(){
    17     fill(you,you+10000,1);
    18     for(int i=N;i>=1;i--){
    19         for(int j=i-1;j>=1;j--){
    20             if(a[j]>a[i]) you[j]=max(you[j],you[i]+1);
    21         }
    22     }
    23 }
    24 int main(){
    25     freopen("01.txt","r",stdin);
    26     scanf("%d",&N);
    27     for(int i=1;i<=N;i++)
    28         scanf("%d",&a[i]);
    29     
    30     zuo_();
    31     you_();
    32     int ans=0;
    33 
    34     
    35     for(int i=1;i<=N;i++)
    36         ans=max(ans,zuo[i]+you[i]-1);
    37     if(ans==1) puts("0");
    38     else printf("%d
    ",N-ans);
    39     return 0;
    40 }
    View Code
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 相关阅读:
    centos 7.5 snmp 安装
    centos 7.5 telnet 离线安装
    使用httpClient发送请求(支持https)
    kafka基本概念
    List根据时间字符串排序
    mac安装yosys遇到`dyld: malformed mach-o image`报错
    ctags的--exclude选项
    每周分享(3)
    实践OKR极易出现的四大误区
    从OKR小白到成功落地OKR(三)
  • 原文地址:https://www.cnblogs.com/radiumlrb/p/5782557.html
Copyright © 2020-2023  润新知