版权声明:大家随意浏览。 https://blog.csdn.net/sinat_30062549/article/details/51297743
题意:给一个长度为n的数字序列A,找到一个长度为2*k+1的子序列,使得前k+1个数单调上升,后k+1个数单调递减。输出2*k+1。
题解:
用cnt1[i]记录给定数组A到第i个元素,最长上升子序列的长度。求最长上升子序列的长度链接:http://blog.csdn.net/sinat_30062549/article/details/47193899
翻转数组A得到数组B
用cnt2[i]记录给定数组B到第i个元素,最长上升子序列的长度。
则,cnt[n-1-i]表示数组A中从i到n-1最长下降子序列的长度。
min(cnt1[i],cnt2[n-1-i])表示以第i个元素为中心的(k+1)的大小。
遍历i(0<=i<n)得到最大的k+1,记为ans。
输出2*ans-1为答案。
代码:
扫描二维码关注公众号,回复:
3045719 查看本文章
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10005;
int a[maxn];
int b[maxn];
int dp[maxn];
int cnt1[maxn];
int cnt2[maxn];
int n;
int lis(int *a){
int len = 1;dp[1] = a[0];
cnt1[0] = 1;
for(int i = 1;i<n;i++){
int t = a[i];
if(t>dp[len]){dp[++len] = a[i];cnt1[i] = len;}
else{
int p = lower_bound(dp+1,dp+len+1,t)-dp;
dp[p] = t;
cnt1[i] = p;
}
}
return len;
}
int main(){
while(cin>>n){
for(int i = 0;i<n;i++){
cin>>a[i];
b[n-1-i] = a[i];
}
int len1 = lis(a);
for(int i = 0;i<n;i++){
cnt2[i] = cnt1[i];
}
int len2 = lis(b);
/* for(int i = n-1;i>=0;i--)
cout<<cnt1[i]<<" ";
cout<<endl;
for(int i = 0;i<n;i++)
cout<<cnt2[i]<<" ";
cout<<endl;*/
int ans = 0;
for(int i = 0;i<n;i++){
int mi = min(cnt2[i],cnt1[n-1-i]);
ans = max(mi,ans);
}
cout<<ans*2-1<<endl;
}
}