DZY has a sequence a, consisting of n integers.
We'll call a sequence ai, ai + 1, ..., aj (1 ≤ i ≤ j ≤ n) a subsegment of the sequence a. The value (j - i + 1) denotes the length of the subsegment.
Your task is to find the longest subsegment of a, such that it is possible to change at most one number (change one number to any integer you want) from the subsegment to make the subsegment strictly increasing.
You only need to output the length of the subsegment you find.
The first line contains integer n (1 ≤ n ≤ 105). The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109).
In a single line print the answer to the problem — the maximum length of the required subsegment.
6 7 2 3 1 5 6
5
You can choose subsegment a2, a3, a4, a5, a6 and change its 3rd element (that is a4) to 4.
题意:
给一个有n个数字的序列,问最多只可以改变一个数字的前提下,最长上升子序列的长度是多少?(严格上升,也就是不能相等)。
解法:
我是先把每一段的最长子序列先用数组b表示。数组b表示最长的上升子序列末尾数字的位置。然后从pos=1开始在a序列往后找,遇到当前数字小于前一个数字开始进行判断。选择改变当前数字,是在前一个数字上+1,还是-1,这个取决于前面序列+后面序列大还是后面序列+前面序列大。好吧,看起来好像是一样,其实不然。举个例子。
序列:1 3 6 4 2 3 4 6。当我们取到第五个数字2的时候,我们是把2变成5还是把前面的4变成1,这个当然改变4为1时子序列最大为5。如果序列是:1 3 2 4 2 6 7 8。同样我们取到第五个数字2的时候,改变2为5时子序列最大为6。这就是两种情况的不同需要考虑。当然最后还有一个特殊情况。本来就是严格的递增序列,所以就直接呵呵了。嗯,直接上代码。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
using namespace std;
#define Max(a,b) a>b?a:b
int n,i;
int a[100010];
int b[100010];
int main()
{
scanf("%d",&n);
a[0]=0;
b[n+1]=0x3fffffff;
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
for (i=n;i>0;i--)
if (a[i]<a[i+1]) b[i]=b[i+1];
else b[i]=i;
int pos=1;
int max=0;
for (i=1;i<=n;i++)
{
if (a[i]<=a[i-1])
{
if (a[i]-1<=a[i-2])
max=Max(max,b[i]-i+2);
else max=Max(max,b[i]-pos+1);
if (a[i-1]+1>=a[i+1])
max=Max(max,i-pos+1);
else max=Max(max,b[i]-pos+1);
pos=i;
}
}
if (pos==1) max=n;
printf("%d\n",max);
return 0;
}