列表

详情


HJ24. 合唱队

描述

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

K位同学从左到右依次编号为 1,2…,K ,他们的身高分别为 ,若存在 使得,则称这K名同学排成了合唱队形。
通俗来说,能找到一个同学,他的两边的同学身高都依次严格降低的队形就是合唱队形。
例子:
123 124 125 123 121 是一个合唱队形
123 123 124 122不是合唱队形,因为前两名同学身高相等,不符合要求
123 122 121 122不是合唱队形,因为找不到一个同学,他的两侧同学身高递减。


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

注意:不允许改变队列元素的先后顺序 不要求最高同学左右人数必须相等

数据范围:

输入描述

用例两行数据,第一行是同学的总数 N ,第二行是 N 位同学的身高,以空格隔开

输出描述

最少需要几位同学出列

示例1

输入:

8
186 186 150 200 160 130 197 200

输出:

4

说明:

由于不允许改变队列元素的先后顺序,所以最终剩下的队列应该为186 200 160 130或150 200 160 130

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C 解法, 执行用时: 2ms, 内存消耗: 328KB, 提交时间: 2021-09-22

#include <stdio.h>

int search_binary(int *nums,int top,int tgt)
{
    int mid;
    int left = 0,right = top;
    while(left <= right)
    {
        mid = (left + right)/2;
        if(tgt > nums[mid])
            left = mid+1;
        else
            right = mid-1;
    }
    return left;
}

void calc_dp(int N,int *nums,int *dp)
{
    int i;
    int top = 0;
    int stk[3072];
    stk[top] = nums[0];
    for(int i = 0; i < N; ++i)
    {
        if(nums[i] > stk[top])
        {
            stk[++top] = nums[i];
            dp[i] = top;
        }
        else
        {
            int pos = search_binary(stk,top,nums[i]);
            stk[pos] = nums[i];
            dp[i] = pos;
        }
    }
}

int main()
{
    int N;
    int max,tmp;
    int nums[3000];
    int dp_l[3072],dp_r[3072];
    while(scanf("%d", &N) != EOF)
    {
        for(int i = 0; i < N; i++)
        {
            scanf("%d",nums+i);
            dp_l[i] = dp_r[i] = 1; 
        }
        calc_dp(N,nums,dp_l);
        for(int i = 0,j = N-1; i < j; ++i,--j)
        {
            tmp = nums[i];
            nums[i] = nums[j];
            nums[j] = tmp;
        }
        calc_dp(N,nums,dp_r);
        max = 0;
        for(int i = 0,j=N-1; i < N; ++i,--j)
        {
            tmp = dp_l[i] + dp_r[j];
            max = tmp > max ? tmp : max; 
        }
        printf("%d\n",N-max-1);
    }
    return 0;
}

C 解法, 执行用时: 2ms, 内存消耗: 348KB, 提交时间: 2020-12-06

#include <stdio.h>

const int sz = 3072;
int search_binary(int *nums, int top, int tgt){
    int mi;
    int lo = 0;
    int hi = top;
    while(lo <= hi){
        mi = lo + (hi - lo) / 2;
        if(tgt > nums[mi]) lo = mi + 1;
        else hi = mi - 1;
    }
    return lo;
}
void calc_dp(int N, int *nums, int *dp){
    int i;
    int top = 0;
    int stk[sz];
    stk[top] = nums[0];
    for(i = 0; i < N; ++i){
        if(nums[i] > stk[top]){
            stk[++top] = nums[i];
            dp[i] = top;
        }
        else{
            int pos = search_binary(stk, top, nums[i]);
            stk[pos] = nums[i];
            dp[i] = pos;
        }
    }
}
int main(void){
    int max;
    int N;
    int tmp;
    int i, j;
    int nums[sz];
    int dp_d[sz];
    int dp_a[sz];
    while(scanf("%d", &N) == 1){
        for(i = 0; i < N; ++i){
            scanf("%d", nums + i);
            dp_d[i] = dp_a[i] = 1;
        }
        calc_dp(N, nums, dp_a);
        for(i = 0, j = N - 1; i < j; ++i, --j){
            tmp = nums[i];
            nums[i] = nums[j];
            nums[j] = tmp;
        }
        calc_dp(N, nums, dp_d);
        max = 0;
        for(i = 0, j = N-1; i < N; ++i, --j){
            tmp = dp_a[i] + dp_d[j];
            if(tmp > max) max = tmp;
        }
        printf("%d\n", N - max - 1);
    }
    return 0;
}

上一题