1. 程式人生 > 實用技巧 >CodeForces 446A. DZY Loves Sequences(最長上升子序列)

CodeForces 446A. DZY Loves Sequences(最長上升子序列)

題意:給定一個長度為n的序列,可以修改任何一個字元,求修改後最長的單調嚴格上升子序列(必須是連續的)。

分析:\((1 <= n < 10^5)\),資料範圍很大,不能使用\(o(n^2)\)的演算法。所以我們可以從線性角度考慮,一種常見的套路是列舉修改點,然後求最大值。我們只需要分別求出兩端的情況即可,從開頭到結尾的以第i個數結尾的最長上升子序列,和從結尾到開頭的以第i個數開頭的最長上升子序列。然後列舉修改點,只要\(a[i + 1] - a[i] >= 2\),那麼這兩個最長的子序列就可以連線起來,更新答案。

注意除了這種情況,我們還可以不連線起來,這種情況一定不要忘記,這樣也可以更新答案。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
using LL = long long;
const int N = 100005;
LL a[N];
int f[N];
int f2[N];
int main()
{
	int n;
	scanf("%d", &n);

	for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);

	if (n == 1)
	{
		puts("1");
	}
	else if (n == 2)
	{
		puts("2");
	}
	else
	{
		f[1] = 1;
		for (int i = 2; i <= n; ++i)
		{
			f[i] = 1;
			if (a[i] > a[i - 1]) f[i] = f[i - 1] + 1;
		}

		f2[n] = 1;
		for (int i = n - 1; i >= 1; --i)
		{
			f2[i] = 1;
			if (a[i] < a[i + 1]) f2[i] = f2[i + 1] + 1;
		}

		int res = 0;
		//修改一個
		for (int i = 1; i <= n - 1; ++i)
		{
			if (a[i] >= a[i + 1]) res = max(res, f[i] + 1);
		}

		for (int i = n - 1; i >= 1; --i)
		{
			if (a[i] >= a[i + 1]) res = max(res, f2[i + 1] + 1);
		}

		for (int i = 2; i <= n - 1; ++i)
		{
			if (a[i + 1] - a[i - 1] >= 2) res = max(res, f2[i + 1] + f[i - 1] + 1);
		}


		printf("%d\n", res);
	}


	return 0;
}