此题需要求某一区间内的出现最多次数的数的出现次数,此题有个好处就是它是非递减序列。题目的输入输出就让人想起了线段树。。。。
每个节点需要保存三个值,一个是区间左边相同数的次数,一个数是区间右边相同数的次数,一个是最多出现次数的个数
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int MAX=1e5+20;
int a[MAX],b[MAX],c[MAX];
typedef struct
{
int lnum,rnum,mnum;
}Node;
Node no[4*MAX];
void build(int L,int R,int id)
{
if(L==R)
{
no[id].mnum=1;
no[id].lnum=1;
no[id].rnum=1;
return;
}
int mid=(R+L)>>1;
build(L,mid,id<<1);
build(mid+1,R,id<<1|1);
no[id].lnum=no[id<<1].lnum;
no[id].rnum=no[id<<1|1].rnum;
int len=0;
if(b[mid]==b[mid+1])
{
if(b[L]==b[mid])
no[id].lnum=mid-L+1+no[id<<1|1].lnum;
if(b[R]==b[mid+1])
no[id].rnum=no[id<<1].rnum+R-mid;
len=no[id<<1].rnum+no[id<<1|1].lnum;
}
no[id].mnum=max(no[id<<1].mnum,no[id<<1|1].mnum);
no[id].mnum=max(no[id].mnum,len);
}
int query(int L,int R,int s,int t,int id)
{
if(s>R||t<L)
return 0;
if(s==L&&t==R)
return no[id].mnum;
int mid=(L+R)>>1;
if(t<=mid)
return query(L,mid,s,t,id<<1);
if(s>mid)
return query(mid+1,R,s,t,id<<1|1);
if(t>mid&&s<=mid)
{
int len0=0;
if(b[mid]==b[mid+1])
len0=min(no[id<<1].rnum,mid-s+1)+min(no[id<<1|1].lnum,t-mid);
//len0=no[id<<1].rnum+no[id<<1|1].lnum;
int len1=query(L,mid,s,mid,id<<1);
int len2=query(mid+1,R,mid+1,t,id<<1|1);
len0=max(len1,len0);
len0=max(len0,len2);
return len0;
}
}
int main()
{
int n,q,i,j,s,t;
while(scanf("%d",&n)&&n)
{
mem(a);
mem(b);
mem(c);
scanf("%d",&q);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
b[1]=1;
for(i=2;i<=n;i++)
{
if(a[i]==a[i-1])
b[i]=b[i-1];
else
b[i]=b[i-1]+1;
}
build(1,n,1);
while(q--)
{
scanf("%d%d",&s,&t);
printf("%d\n",query(1,n,s,t,1));
}
}
return 0;
}