二分+线性dp模板题:洛谷《合唱队形》的python题解

题目描述

n 位同学站成一排,音乐老师要请其中的 n−k 位同学出列,使得剩下的 k 位同学排成合唱队形。

合唱队形是指这样的一种队形:设 k 位同学从左到右依次编号为 1,2, … ,k,他们的身高分别为 t1​,t2​, … ,tk​,则他们的身高满足 t1​<⋯<ti​>ti+1​> … >tk​(1≤i≤k)。

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

输入格式

共二行。

第一行是一个整数 n(≤n≤100),表示同学的总数。

第二行有 n 个整数,用空格分隔,第 i 个整数 ti​(130≤ti​≤230)是第 i 位同学的身高(厘米)。

输出格式

一个整数,最少需要几位同学出列。

输入输出样例

输入 

8
186 186 150 200 160 130 197 220

输出

4

说明/提示

对于 50% 的数据,保证有 n≤20。

对于全部的数据,保证有 n≤100。

前置知识:线性dp,最长上升子序列的nlogn优化,二分查找(和洛谷的导弹拦截都是这类题型的模板题

分析:

  1. 最少几个同学出列,其实就是求解最多几个同学能组成满足条件的序列
  2. 根据题意这个序列可以是一部分(完全严格上升或严格下降子序列)也可以是两部分(前面严格上升后面严格下降)
  3. 我们可以用ans1存上升部分的长度(ans1[i]表示到第i个数能形成的最长上升序列的长度,ans2类似),up存上升序列,ans2存下降部分,down存下降部分
  4. 两个ans都是在序列能变长时等于前面一个ans+1,不能变长就等于前面一个ans
  5. 最后将ans1和ans2打包求和就行

上AC代码

def check(l, obj, key):  # 这个列表是从一个开始生成的,所以不能用bisect函数来简单书写。多传入参数是为了加快python的查找速度
    """不相等时要右边那一位"""
    i, j = 0, l-1
    while i < j:
        m = i+j >> 1
        if obj[m] == key:  # 严格上升子序列里相等不用进行任何操作
            return m
        elif obj[m] > key:
            j = m
        else:
            i = m+1
    return i


n = int(input())
a = list(map(int, input().split()))
up = [a[0]]
down = [a[-1]]
ans1 = [1]*n
ans2 = [1]*n
for i in range(1, n):
    if a[i] > up[-1]:
        ans1[i] = ans1[i-1]+1
        up.append(a[i])
    else:
        ans1[i] = ans1[i-1]
        up[check(ans1[i], up, a[i])] = a[i]
    if a[n-1-i] > down[-1]:  # 倒着取少写一个二分,即都是求严格上升子序列了
        ans2[n-1-i] = ans2[n-i]+1
        down.append(a[n-1-i])
    else:
        ans2[n-1-i] = ans2[n-i]
        down[check(ans2[n-1-i], down, a[n-1-i])] = a[n-1-i]
print(n-max([i+j-1 for i, j in zip(ans1, ans2)]))

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈子昂-北工大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值