#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
const int N=1e5+10,M=0,Z=1e9+7,ms63=1061109567;
int n;
int a[N];
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;++i)scanf("%d",&a[i]);a[0]=a[n+1]=-1;
int ans=0;
//i是第一个数的开头,j是第二个数的开头
int i=1;
int j=2;while(a[j]==a[i])++j;
gmax(ans,j-i);
/*然后,我们一直滚动,记录第一个数和第二个数的首位置,直到找到第三个数。并更新答案。
之后再把第二个数当做第一个数,把第三个数当做的第二个数,并再重复上面的过程。直到最后。
但是这里要注意,可能会出现{x x+1 x x+1 x+2}这种情况,
所以我们可以向后转移的第三个数的位置需要动态更新,更新为最后一个a[j]!=a[j-1]的位置即可*/
while(j<=n)
{
int x=a[j];int p=j;
for(++j;a[j]==a[i]||a[j]==x;++j)if(a[j]!=a[j-1])p=j;
gmax(ans,j-i);
i=p;
}
printf("%d\n",ans);
}
return 0;
}
/*
【trick&&吐槽】
这题肯定有暴力水过的做法>_<
所以如果遇到实在不会的时候,可以考虑冲一发暴力哦!
【题意】
给你n(1e5)个数,每个数的范围都是在([1,1e5])。而且相邻两个数的差值只可能是{-1,0,+1}
我们接下来要找一个长度最长的序列,使得该序列的最大值与最小值之差最大只能为1。
【类型】
贪心 多指针
【分析】
如何才算是分析问题的合理思路?
最大值与最小值的差值最大只能为1,于是,对于这个长度最长的序列,其实就只存在两种情况——
情况1:所有数都相同,所有数都为x。
情况2:数值只可能为2个,x以及x+1。
首先,我们可以直接通过while(1)的方式,向右贪心滚动到不能滚动为止。
因为相邻的数的差值一定不超过1,于是这个时候,一定只存在2种可能——
(x x+1 x+2)
(x+1 x x-1)
我们只要记录第一个数,第二个数,第三个数的三个适当位置,并恰当转移,即可用O(n)复杂度时间解决问题。
然而一定要注意细节哦>_<!
【时间复杂度&&优化】
O(n)
*/
【Codeforces Round 333 (Div 2)B】【贪心 多指针】Approximating a Constant Range 给定数组 相邻元素波动为1 求差值不超1的最长序连续子序列
最新推荐文章于 2022-09-15 13:40:07 发布