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 }
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 }
Codeforces Round #333 (Div. 2) B. Approximating a Constant Range