D. Remove One Element (DP)

You are given an array a consisting of n integers.

You can remove at most one element from this array. Thus, the final length of the array is n−1 or n.

Your task is to calculate the maximum possible length of the strictly increasing contiguous subarray of the remaining array.

Recall that the contiguous subarray a with indices from l to r is a[l…r]=al,al+1,…,ar. The subarray a[l…r] is called strictly increasing if al<al+1<⋯<ar.

Input
The first line of the input contains one integer n (2≤n≤2⋅105) — the number of elements in a.

The second line of the input contains n integers a1,a2,…,an (1≤ai≤109), where ai is the i-th element of a.

Output
Print one integer — the maximum possible length of the strictly increasing contiguous subarray of the array a after removing at most one element.

Examples

5
1 2 5 3 4

4

Note
In the first example, you can delete a3=5. Then the resulting array will be equal to [1,2,3,4] and the length of its largest increasing subarray will be equal to 4.

題目大意:
給你一個長度爲 n 的數組,你最多刪除一個元素(也可以不刪),求此條件限制下的最長上升子串長度。

解題思路:

首先這裏有一個條件“你最多可以刪除一個元素”,這個條件會造成我們很多的困擾,所以爲了避免困擾,我們先嚐試在沒有這個條件的情況下解決問題。

在我們沒有刪除元素的權限下,數組 a 中的 n 個元素是固定的,所以此時我們可以定義狀態 f[i] 表示以 a[i] 結尾並且包含 a[i] 的最長上升子串的長度,那麼我們可以發現(設數組座標從 1 開始):

f[1]=1;
當 i>1 時,
如果 a[i−1]<a[i] ,則 f[i]=f[i−1]+1
否則,f[i]=1

然後我們需要求的最長上升子串長度就是所有 f[i] 中最大的那個。
稍等一下,我們暫時還是不加上“你最多可以刪除一個元素”這個條件。
在加上這個條件之前,我們再定義一個狀態 g[i] 表示以 a[i] 開頭並且包含 a[i] 的最長上升子串的長度,那麼,我們可以得到狀態轉移方程:

g[n]=1;
當 i<n 時,
如果 a[i]<a[i+1],則 g[i]=g[i+1]+1;
否則,g[i]=1

注意 g[i] 需要從 n 到 1 反着推

那麼我們求完 f[i] 和 g[i] 之後呢,我們再來加回“你最多可以刪除一個元素”這個條件。

首先,如果我們不刪除元素,那麼答案就是所有 f[i] 中的最大值,我們開一個變量 ans=max(f[i])。

其次,如果我們刪除元素的座標是 i ,我們假設刪除元素後的最長上升子串對應爲 a[l] 到 a[r],
那麼如果 i 不滿足 l<i<r 的條件,那麼我刪或者不刪 a[i] 對我答案絲毫不影響(仍然是 ans=max(f[i]))。

那麼什麼時候會對答案有影響呢?
就是當 1<i<n 且 a[i−1]<a[i+1] 的時候,我刪除 a[i] 能夠使得 f[i−1]+g[i+1]>ans 的時候,說明刪除元素 a[i] 達到了增長最長上升子串的效果,此時我們更新 ans=f[i−1]+g[i+1] 。

綜上所述,答案應該是

max(f[i]) (其中 (1≤i≤n))

max(f[i−1]+g[i+1]) (其中 1<i<n 且 a[i−1]<a[i+1])

維護較大值。

ac代碼:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<bitset>
#include<unordered_map>
#include<queue>
#include<stack>
#include<set>
#define pb push_back
#define bp __builtin_popcount
using namespace std;
typedef unsigned long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 1e6 + 100;
const int MOD = 1e9 + 7;
int lowbit(int x) { return x & -x; }
inline ll dpow(ll a, ll b) { ll r = 1, t = a; while (b) { if (b & 1)r = (r * t) % MOD; b >>= 1; t = (t * t) % MOD; }return r; }
inline ll fpow(ll a, ll b) { ll r = 1, t = a; while (b) { if (b & 1)r = (r * t); b >>= 1; t = (t * t); }return r; }
int a[maxn], f[maxn], g[maxn];
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	f[1] = 1;
	for (int i = 2; i <= n; i++)//以a[i]結尾的最長上升子序列的最優解
	{
		
		if (a[i] > a[i - 1])
			f[i] = f[i - 1] + 1;
		else
			f[i] = 1;
	}
	g[n] = 1;
	for (int i = n-1; i >= 1; i--)//以a[i]開頭的最長上升子序列的最優解
	{
		if (a[i] < a[i + 1])
			g[i] = g[i + 1] + 1;
		else
		    g[i] = 1;
	}

	int ans = 0;
	for (int i = 1; i <= n; i++)
		ans = max(ans, f[i]);

	for (int i = 2; i < n; i++)
	{
		if(a[i+1]>a[i-1])
			ans = max(ans, f[i - 1] + g[i + 1]);
	}
	cout << ans << endl;
		
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章