合唱队形
TimeLimit:1000MS MemoryLimit:128MB
64-bit integer IO format:%lld
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
Input
输入的第一行是一个整数N(2<=N<=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130<=Ti<=230)是第i位同学的身高(厘米)。
Output
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
SampleInput
8
186 186 150 200 160 130 197 220
SampleOutput
4
这题就是lis(最长上升子列)的双向版本。
关于lis 请转步https://blog.youkuaiyun.com/qq_43563669/article/details/86546134
要求最少的出列个数,也就是留下的人最多。那么只需要让第i个同学为最高的人, 两边求lis求和减去1就行了,注意求lis时候,先判断是不是小于这个最高的同学。。。遍历找最大,然后n-max就是最小的了。。。。博主为了省事,直接把i设为全局变量,然后循环输出和单独输出结果一直不一样。。ORZ。。
#include<bits/stdc++.h>
using namespace std;
int a[105],i,n;
int llis(int m)//求左边的lis
{
int b[105]= {0},len=1;
for(i=1; i<=m; i++)
{
if(a[i]>=a[m])
continue;
else
{
if(a[i]>b[len])
b[++len]=a[i];
else
{
b[lower_bound(b+1,b+len+1,a[i])-b]=a[i];
}
}
}
return len;
}
int rlis(int m)///求右边的lis
{
int b[105]= {0},len=1;
for(i=n; i>=m; i--)
{
if(a[i]>=a[m])
continue;
else if(a[i]>b[len])
b[++len]=a[i];
else
{
b[lower_bound(b+1,b+len+1,a[i])-b]=a[i];
}
}
return len;
}
int main()
{
int i;
cin>>n;
for(i=1; i<=n; i++)
cin>>a[i];
int max=0;
for(i=1; i<=n; i++)///遍历找最大
if(rlis(i)+llis(i)-1>max)///两边最大都是a[i] 重复了一个需要减去,
max=rlis(i)+llis(i)-1;
cout<<n-max<<endl;
}
本文详细解析了一种称为合唱队形的算法问题,旨在找出最少需要几位同学出列,以便剩下的同学能形成特定的身高队形。通过计算最长上升子序列(LIS)的双向版本,博主提供了一个高效的解决方案。
1181

被折叠的 条评论
为什么被折叠?



