#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX= 100005;
int n,q,li[MAX];
struct Num
{
int num,st,en,cnt;
}number[MAX],bt[MAX*4];
Num inital(int l,int r,int k)//初始化函数,其实应该算是建树,不过只是一个名字,随便了
{
if(r-l==1)
return bt[k]=number[l];
Num num1=inital(l,(l+r)/2,k*2+1);
Num num2=inital((l+r)/2,r,k*2+2);
if(num1.cnt>num2.cnt)
return bt[k]=num1;
else
return bt[k]=num2;
}
int query(int a,int b,int l,int r,int k)//询问a,b区间的最大值,(l,r)代表当前所在区间,k为所在区间的节点编号
{
if(l>=a&&r<=b)
return bt[k].cnt;
if(r<=a||l>=b)
return 0;
return max(query(a,b,l,(l+r)/2,k*2+1),query(a,b,(l+r)/2,r,k*2+2));
}
bool cmp( const Num& t1, const Num& t2 )
{
return t1.st<=t2.st;
}
int main()
{
while(cin>>n&&n)
{
cin>>q;
int t,k=0;
cin>>number[0].num;
number[0].cnt=1;number[0].st=0;number[0].en=1;
for(int i=1;i<n;i++)
{
scanf("%d",&t);
if(t==number[k].num)
{
number[k].cnt++;
number[k].en++;
}
else
{
k++;
number[k].num=t;
number[k].cnt=1;
number[k].st=number[k-1].en;
number[k].en=number[k].st+1;
}
}
k++;
inital(0,k,0);//个人随便写的初始化函数,请勿模仿
for(int i=0;i<k;i++)//多此一举,本想用stl的,不过当时不知道怎么用在struct中,所以只好这样了
li[i]=number[i].st;
for(int i=0;i<q;i++)
{
int l,r,ans;
scanf("%d%d",&l,&r);
l--;r--;
int l0=l,r0=r;
l=upper_bound(li,li+k,l)-li;
r=upper_bound(li,li+k,r)-li;
l--,r--;
if(r-l>0)
ans=max(r0-number[r].st+1,number[l].en-l0);
else
ans=r0-l0+1;//如果都在同一区间,直接求长度
if(r-l>1)
ans=max(ans,query(l+1,r,0,k,0));//如果区间跨度太大的话,搜索中间的区间
printf("%d\n",ans);
}
}
return 0;
}
此题算是一个简单的线段树,但是我因为stl库的问题纠结了半天最后只能无奈这么写了,A完之后看了一下别人的代码发现差异还是有点大的所以也懒得看别人的代码了。
虽是A了,却有很多地方需要改进。不过作为我第一个没有参考模板的线段树,还是挺有成就感的