Codeforces Round #333 (Div. 2) B. Approximating a Constant Range

B. Approximating a Constant Range

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://codeforces.com/contest/602/problem/B

Description

When Xellos was doing a practice course in university, he once had to measure the intensity of an effect that slowly approached equilibrium. A good way to determine the equilibrium intensity would be choosing a sufficiently large number of consecutive data points that seems as constant as possible and taking their average. Of course, with the usual sizes of data, it's nothing challenging — but why not make a similar programming contest problem while we're at it?

You're given a sequence of n data points a1, ..., an. There aren't any big jumps between consecutive data points — for each 1 ≤ i < n, it's guaranteed that |ai + 1 - ai| ≤ 1.

A range [l, r] of data points is said to be almost constant if the difference between the largest and the smallest value in that range is at most 1. Formally, let M be the maximum and m the minimum value of ai for l ≤ i ≤ r; the range [l, r] is almost constant if M - m ≤ 1.

Find the length of the longest almost constant range.

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 100 000) — the number of data points.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 100 000).

Output

Print a single number — the maximum length of an almost constant range of the given sequence.

Sample Input

5
1 2 3 3 2

Sample Output

4

HINT

 

题意

给你n个数,要求你找到最长的区间,使得这个区间的最大值减去最小值之差的绝对值小于等于1

题解:

我是先做到它的升级版:此题升级版

我大概讲一下吧:

不难发现:如果(l,r),那么(l+1,r)必然也合法。

所以我们枚举左端点,右端点是不断递增的,所以是线性的。

可以用ST表做,也可以用优先队列做。

 

优先队列代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100050
 4 int n,val[N],flag[N];
 5 struct Node
 6 {
 7   int id,val;
 8   bool operator <(const Node&b)const
 9   {return val<b.val;}
10 };
11 template<typename T>void read(T&x)
12 {
13   int k=0; char c=getchar();
14   x=0;
15   while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
16   if (c==EOF)exit(0);
17   while(isdigit(c))x=x*10+c-'0',c=getchar();
18   x=k?-x:x;
19 }
20 int main()
21 {
22   #ifndef ONLINE_JUDGE
23   freopen("aa.in","r",stdin);
24   #endif
25   read(n);
26   for(int i=1;i<=n;i++)read(val[i]);
27   int r=0,ans=0;
28   priority_queue<Node>mx,mi;
29   for(int i=1;i<=n;i++)
30     {
31       while(r+1<=n&&(mi.empty()||
32              (fabs(val[r+1]-mx.top().val)<=1&&fabs(val[r+1]+mi.top().val)<=1)))
33     {
34       mx.push(Node{r+1,val[r+1]});
35       mi.push(Node{r+1,-val[r+1]});
36       r++;
37     }
38       ans=max(ans,r-i+1);
39       flag[i]=1;
40       while(!mi.empty()&&flag[mi.top().id])mi.pop();
41       while(!mx.empty()&&flag[mx.top().id])mx.pop();
42     }
43   printf("%d\n",ans);
44 }
View Code

 

ST表代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100050
 4 int n,val[N];
 5 int mm[N],mi[N][20],mx[N][20];
 6 template<typename T>void read(T&x)
 7 {
 8   int k=0; char c=getchar();
 9   x=0;
10   while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
11   if (c==EOF)exit(0);
12   while(isdigit(c))x=x*10+c-'0',c=getchar();
13   x=k?-x:x;
14 }
15 void init_ST(int n)
16   {
17     mm[0]=-1;
18     for(int i=1;i<=n;i++)
19       {
20     mm[i]=(i&(i-1))==0?mm[i-1]+1:mm[i-1];
21     mx[i][0]=mi[i][0]=val[i];
22       }
23     for(int i=1;i<=20;i++)
24       for(int j=1;j+(1<<i)-1<=n;j++)
25     {
26       mi[j][i]=min(mi[j][i-1],mi[j+(1<<(i-1))][i-1]);
27       mx[j][i]=max(mx[j][i-1],mx[j+(1<<(i-1))][i-1]);
28     }
29   }
30 int rmq(int x,int y)
31   {
32     int k=mm[y-x+1];
33     int ans=max(mx[x][k],mx[y-(1<<k)+1][k]);
34     ans-=min(mi[x][k],mi[y-(1<<k)+1][k]);
35     return ans;
36   }
37 int main()
38 {
39   #ifndef ONLINE_JUDGE
40   freopen("aa.in","r",stdin);
41   #endif
42   read(n);
43   for(int i=1;i<=n;i++)read(val[i]);
44   init_ST(n);
45   int r=0,ans=0;
46   for(int i=1;i<=n;i++)
47     {
48       while(r+1<=n&&rmq(i,r+1)<=1)r++;
49       ans=max(ans,r-i+1);
50     }
51   printf("%d\n",ans);
52 }
View Code

 

转载于:https://www.cnblogs.com/mmmqqdd/p/10827794.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值