奈芙莲的序列
Problem Description
有一天可爱的Nephren得到了一个序列,一开始,她取出序列的第一个数,形成一个新的序列B,然后取出序列A的第二个数,放在序列B的最左边或最右边,序列B此时有两个数,下一步,再取出序列A的第三个数放在序列B的最左边或最右边,……
现在的问题是,通过上面的步骤,可以得到B的最长上升子序列的长度是多少
Input
第一行,一个整数N.
第二行,N个整数,表示序列A。
Output
一行一个整数,表示最长上升子序列的长度
Sample Input
4
2 1 3 4
Sample Output
4
题解:
只考虑组成最长序列的那些数字,其他数字忽略。当最长的序列的第一个元素放入B序列后,剩下的数字要不比B小,靠左放;要不比B大,向右放;要不就不是最长序列的一部分。
将数组逆序,分别求出每个位置的LIS和最长下降子序列,设为dp1和dp2,结果为
的最大值。
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-7
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 200100;
const int mod = 1000000007;
int a[maxn], dp1[maxn], dp2[maxn], g1[maxn], g2[maxn];
int main()
{
int n, i, j, k, pos;
int top1 = 0, top2;
scanf("%d", &n);
for(i=1;i<=n;i++)
scanf("%d", &a[i]);
for(i=n;i>=1;i--){
pos = lower_bound(g1, g1+top1, a[i])-g1;
if(pos == top1)top1++;
g1[pos] = a[i];
dp1[i] = pos+1;
}
top2 = n;
for(i=n;i>=1;i--){
pos = upper_bound(g2+top2, g2+n, a[i])-g2;
if(pos == top2)top2--;
g2[pos-1] = a[i];
dp2[i] = n-pos+1;
}
int ans = 1;
for(i=1;i<=n;i++)
ans = max(ans, dp1[i]+dp2[i]-1);
printf("%d\n", ans);
return 0;
}