原文:http://blog.acmj1991.com/?p=695
题意:给你一个非递减数列,求给定区间内最大的连续相等的个数。
思路:线段树 这里线段树回溯是不能之比较两子树的最大值,还要比较合并者后可能产生的连续相等的数。所以回溯的时候得比较一下中间连续的值。同时查询的时候也要比较中间值
#include<stdio.h>
#include<string.h>
#define L(x)(x<<1)
#define R(x)(x<<1|1)
#define maxN 100010
int ll[maxN],rr[maxN],key[maxN];
struct node{
int l,r,c;
}p[4*maxN];
void init(){
memset(ll,0,sizeof(ll));
memset(rr,0,sizeof(rr));
}
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int Build_tree(int l,int r,int st)
{
p[st].l=l,p[st].r=r,p[st].c=1;
if(l==r){
return p[st].c;
}
int mid=(l+r)>>1;
p[st].c=max(Build_tree(l,mid,L(st)),Build_tree(mid+1,r,R(st)));
if(key[mid]==key[mid+1]){
int sum=0;
sum+=min(ll[mid]+1,mid-l+1);
sum+=min(rr[mid],r-mid);
p[st].c=max(p[st].c,sum);
}
return p[st].c;
}
int query(int l,int r,int st)
{
if(p[st].l==l&&p[st].r==r)
return p[st].c;
int mid=(p[st].l+p[st].r)>>1;
if(r<=mid)return query(l,r,L(st));
else if(l>mid)return query(l,r,R(st));
else{
int sum=0;
if(key[mid]==key[mid+1]){
sum+=min(ll[mid]+1,mid-l+1);
sum+=min(rr[mid],r-mid);
}
sum=max(query(l,mid,L(st)),sum);
return max(sum,query(mid+1,r,R(st)));
}
}
int main()
{
int n,m,x,y;
while(scanf("%d",&n)&&n)
{
scanf("%d",&m);
init();
for(int i=1;i<=n;i++)
scanf("%d",&key[i]);
for(int i=2;i<=n;i++)
if(key[i]==key[i-1])
ll[i]=ll[i-1]+1;
for(int i=n-1;i>0;i--)
if(key[i]==key[i+1])
rr[i]=rr[i+1]+1;
Build_tree(1,n,1);
while(m--){
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y,1));
}
}
}