UVA 10534 - Wavio Sequence

大意不再赘述。

思路:一开始看错题,以为是从端点左边开始的最长上升子序列与下降子序列,后来发现是端点从左边开始的最长上升子序列,端点从右边开始的最长下降子序列。而且题目有一个陷阱,就是LIS不一定等于LDS,但序列一定是对称的,所以ans = max(ans, min(d1[i], d2[i])-1);

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
using namespace std;

const int MAXN = 10010;
const int INF = 0x3f3f3f3f;

int A[MAXN];
int S[MAXN];
int d1[MAXN], d2[MAXN];

int n, m;

void init()
{
	for(int i = 1; i <= n; i++) S[i] = INF;
}

int BSearch(int x, int y, int v)
{
	while(x <= y)
	{
		int m = x+(y-x)/2;
		if(S[m] < v) x = m+1;
		else y = m-1;
	}
	return x;
}

void LIS(int n)
{
	init();
	int ans = 0;
	for(int i = 1; i <= n; i++)
	{
		int x = 1, y = i;
		int pos = BSearch(x, y, A[i]);
		d1[i] = pos;
		S[d1[i]] = min(S[d1[i]], A[i]);
		ans = max(ans, d1[i]);
	}
}

void LDS(int n)
{
	init();
	int ans = 0;
	for(int i = n; i >= 1; i--)
	{
		int x = 1, y = i;
		int pos = BSearch(x, y, A[i]);
		d2[i] = pos;
		S[d2[i]] = min(S[d2[i]], A[i]);
		ans = max(ans, d2[i]);
	}
}

void read_case()
{
	for(int i = 1; i <= n; i++) scanf("%d", &A[i]);
}

/*int check(int a, int b)
{
	if(a == b && (a+b-1) & 1) return 1;
		return 0;
}*/

void solve()
{
	read_case();
	int ans = 0;
	LIS(n), LDS(n);
	for(int i = 1; i <= n; i++)
	{
		ans = max(ans, 2*min(d1[i], d2[i])-1);
		//if(check(d1[i], d2[i])) ans = max(ans, (d1[i]+d2[i]-1));
		//printf("%d %d\n", d1[i], d2[i]);
	}
	printf("%d\n", ans);
}

int main()
{
	while(~scanf("%d", &n))
	{
		solve();
	}
	return 0;
}


 

你可能感兴趣的:(UVA 10534 - Wavio Sequence)