NOIP模拟题——Mushroom的序列

Mushroom的序列
【问题描述】
Mushroom手中有n个数排成一排,现在Mushroom想取一个连续的子序列,使得这个子序列满足:最多只改变一个数,使得这个连续的子序列是严格上升子序列,Mushroom想知道这个序列的最长长度是多少。
【输入格式】
第一行一个整数n,表示有n个数。
第二行为n个数。
【输出格式】
一个数,为最长长度。
【输入样例】
6
7 2 3 1 5 6
【输出样例】
5
【样例解释】
选择第2个数到第6个数,把1改变成4即可。
【数据范围】
对于30%的数据,n<=10
对于60%的数据,n<=1000
对于100%的数据,n<=100000

拿到数据后首先想到的是O(nlogn)想了很久很久…………

后来发现这道题扫两遍就OK了

第一遍扫描,保存连续递增的区间的左右位置

第二遍扫描直接求出ans:与前一个区间比较,由于区间递增,所以只用判断前区间的right-1和后区间的left,and前区间的right和

后区间的left+1即可。(至于递增区间为1的情况,加一个特判就可以了)

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 const int maxn=100005;
 7 struct node{
 8     int left,right;
 9 }q[maxn];
10 int temp=0;
11 int a[maxn];
12 int n;
13 int main()
14 {
15     freopen("seq.in","r",stdin);
16     freopen("seq.out","w",stdout);
17     scanf("%d",&n);
18     for(int i=1;i<=n;i++)
19     scanf("%d",&a[i]);
20     q[++temp].left=1;
21     for(int i=2;i<=n;i++)
22     {
23         if(a[i]>a[i-1])continue;
24         if(a[i]<=a[i-1])
25         {
26             q[temp].right=i-1;
27             temp++;
28             q[temp].left=i;
29             continue;
30         }
31     }
32     q[temp].right=n;
33     int ans=q[1].right-q[1].left+1;
34     for(int i=2;i<=temp;i++)
35     {
36         if(q[i-1].left==q[i-1].right)//前面为单点区间
37         ans=max(ans,q[i].right-q[i-1].left+1);
38         else if(q[i].left==q[i].right)//后面为单点区间
39         ans=max(ans,q[i].right-q[i-1].left+1); 
40         else
41         {
42             if((a[q[i].left]>a[q[i-1].right-1]+1)||(a[q[i].left+1]>a[q[i-1].right]+1))
43             ans=max(ans,q[i].right-q[i-1].left+1);
44             else
45             {
46                 ans=max(ans,q[i-1].right-q[i-1].left+2);
47                 ans=max(ans,q[i].right-q[i].left+2);
48             }
49         } 
50     }
51     printf("%d",ans);
52     return 0;
53 }
原文地址:https://www.cnblogs.com/937337156Zhang/p/6017128.html