您的位置:首页 > 其它

uva 10534 (dp专组H题)

2016-05-02 19:36 330 查看
题意:给一个长度为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为答案。

代码:

#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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息