原题: 洛谷 P1091合唱队形
思路:
-
本来想的是,写两个函数,lis(int x)求[1,x]的最长上升子序列,一个lcs(int x)求[x,n]的最长下降子序列
然后for(1-n)中每次求一个lis和lcs然后求一个max,结果只过了5个测试点
#include<iostream> #include<algorithm> #include<vector> using namespace std; int n,arr[100],ind; vector<int> t; // [1,x]的最长上升子序列 int lis(int x){ t.clear(); t.push_back(arr[1]); for(int i=2;i<=x;i++){ if(arr[i]>t.back()) t.push_back(arr[i]); else{ ind = lower_bound(t.begin(),t.end(),arr[i])-t.begin(); t[ind] = arr[i]; } } return t.size(); } // [x,n]的最长下降子序列 int lcs(int x){ t.clear(); t.push_back(arr[x]); for(int i=x+1;i<=n;i++){ if(arr[i]<t.back()) t.push_back(arr[i]); else{ ind = upper_bound(t.begin(),t.end(),arr[i],greater<int>())-t.begin(); t[ind] = arr[i]; } } return t.size(); } int main(){ //freopen("data.in","r",stdin); cin>>n; for(int i=1;i<=n;i++) cin>>arr[i]; int mn = 0,a,b; for(int i=1;i<=n;i++){ a = lis(i); b = lcs(i); mn = max(mn,a+b); } cout<<n+1-mn; return 0; }下载下来数据集,和正确的对比了一下中间值,发现问题处在了lcs上,求出来的lcs多多少少会有偏差,思考了一下,可能是upper_bound加上greater惹的祸(未求证),使得求出的不是严格下降子序列,自己尝试写了个cmp来代替greater,结果程序崩溃.....
inline bool cmp(int a,int b){ return a<b; }咋办,不服,还想用upper_bound,试了好久后发现
不服憋着
下边是大佬Rumia 的解法,
- 从前往后求一边lis,并记录下中间值
- 从后往前求一遍lcs(还是用Lis的求法),并记录下中间值
- for(1-n)找出当lis[i]+lcs[i]的最大值
注水代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int n,arr[105],ind,arr2[105],arr3[105];// arr2放lis,arr3放lcs
vector<int> t;
void lis(){
t.clear();
t.push_back(arr[1]);
arr2[1] = 1;
for(int i=2;i<=n;i++){
if(arr[i]>t.back())
t.push_back(arr[i]);
else{
ind = lower_bound(t.begin(),t.end(),arr[i])-t.begin();
t[ind] = arr[i];
}
arr2[i] = t.size();
}
}
void lcs(){
t.clear();
t.push_back(arr[n]);
arr3[n] = 1;
for(int i=n-1;i>=1;i--){
if(arr[i]>t.back())
t.push_back(arr[i]);
else{
ind = lower_bound(t.begin(),t.end(),arr[i])-t.begin();
t[ind] = arr[i];
}
arr3[i] = t.size();
}
}
int main(){
freopen("data.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++)
cin>>arr[i];
lis();
lcs();
int mn = 0,a,b;
for(int i=1;i<=n;i++){
mn = max(mn,arr2[i]+arr3[i]);
}
cout<<n-mn+1;
return 0;
}
ps:总觉得哪里还能优化,比如用了两个函数,但是函数大部分步骤都是一样的,能简化成一个...算了,懒...:kissing_smiling_eyes:
题面:
题目描述
NN位同学站成一排,音乐老师要请其中的(N-KN−K)位同学出列,使得剩下的KK位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K1,2,…,K,他们的身高分别为T_1,T_2,…,T_KT1,T2,…,T**K, 则他们的身高满足T_1<...<T_i>T_{i+1}>…>T_K(1 \le i \le K)T1<...<T**i>T**i+1>…>T**K(1≤i≤K)。
你的任务是,已知所有NN位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入格式
共二行。
第一行是一个整数N(2 \le N \le 100)N(2≤N≤100),表示同学的总数。
第二行有nn个整数,用空格分隔,第ii个整数T_i(130 \le T_i \le 230)T**i(130≤T**i≤230)是第ii位同学的身高(厘米)。
输出格式
一个整数,最少需要几位同学出列。
输入输出样例
输入 #1复制
8
186 186 150 200 160 130 197 220
输出 #1复制
4