您的位置:首页 > 移动开发

codeforces 602B Approximating a Constant Range(线段树+尺取法)

2015-12-08 14:29 447 查看
题目链接:

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

题目大意:

给一段长为N的序列,现在要找一段区间,要求区间里的最大值和最小值之差不超过1,问最大的区间长度是多少。

思路:

在众多的方法前,我选择了最省力又暴力的线段树= =

利用尺取法,定义左右两个指针,维护一段满足条件的最大长度的区间。然后在右指针变化过程中,一旦发现这段区间不符合条件了,就改变左指针,然后每变一次就用线段树算出新区间上面的最大和最小值,直到符合条件为止。

代码:

#include<stdio.h>
#include<string.h>
#define M 100005
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
struct tree{
int l,r,ma,mi;
}tree[M<<2];
int a[M];
void pushup(int i)
{
if(tree[i].l==tree[i].r)return;
tree[i].ma=max(tree[i<<1].ma,tree[i<<1|1].ma);
tree[i].mi=min(tree[i<<1].mi,tree[i<<1|1].mi);
}
void build(int l,int r,int i)
{
tree[i].l=l;
tree[i].r=r;
if(tree[i].l==tree[i].r){
tree[i].ma=tree[i].mi=a[l];
return;
}
int mid=l+r>>1;
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
pushup(i);
}
int query1(int l,int r,int i)
{
if(tree[i].l==l&&tree[i].r==r){
return tree[i].ma;
}
int mid=tree[i].l+tree[i].r>>1;
if(r<=mid)return query1(l,r,i<<1);
else if(l>mid)return query1(l,r,i<<1|1);
else return max(query1(l,mid,i<<1),query1(mid+1,r,i<<1|1));
}
int query2(int l,int r,int i)
{
if(tree[i].l==l&&tree[i].r==r){
return tree[i].mi;
}
int mid=tree[i].l+tree[i].r>>1;
if(r<=mid)return query2(l,r,i<<1);
else if(l>mid)return query2(l,r,i<<1|1);
else return min(query2(l,mid,i<<1),query2(mid+1,r,i<<1|1));
}
int main()
{
int n,i,j,k,maxi,ans,mini;
while(~scanf("%d",&n))
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
int l,r;
l=r=1;
maxi=mini=a[1];
ans=1;
for(i=2;i<=n;i++)
{
r=i;
maxi=max(maxi,a[i]);
mini=min(mini,a[i]);
while(maxi-mini>1){
l++;
maxi=query1(l,r,1);
mini=query2(l,r,1);
}
ans=max(ans,r-l+1);
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: