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 #include2 #include 3 #include 4 #include 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 }