这道题是紫书上198页的题,自己想我还真想不出来,比如游程编码和这么多数组。。
不过书上有一点我变了一下,按照自己的理解写的:p代表的不是p位置而是p位置对应的第i段,left和right数组都要对应变一下,我感觉这样比较好写。附上AC代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int INF=0x3f3f3f3f;
const ll MOD=1e9+7ll;
const int MAX=100005;
int n,q;
int a[MAX];
int r[MAX][20];
int val[MAX],coun[MAX];
int id[MAX],le[MAX],ri[MAX];
void initRMQ(int b[])
{
memset(r,0,sizeof(r));
for(int i=1;i<=n;i++)
r[i][0]=b[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
r[i][j]=max(r[i][j-1],r[i+(1<<(j-1))][j-1]);
}
int rmq(int x,int y)
{
if(x>y)//注意要加
return 0;
int k=log(y-x+1.0)/log(2.0);
return max(r[x][k],r[y-(1<<k)+1][k]);
}
int main()
{
while(scanf("%d",&n)==1)
{
if(n==0)
break;
scanf("%d",&q);
memset(a,0,sizeof(a));
memset(val,0,sizeof(val));
memset(coun,0,sizeof(coun));
memset(id,0,sizeof(id));
memset(le,0,sizeof(le));
memset(ri,0,sizeof(ri));
scanf("%d",&a[1]);
int pre=a[1];
int seg=0;//第i段
val[++seg]=pre;
coun[seg]++;
id[1]=seg;
le[seg]=1;
for(int i=2;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==pre)
{
id[i]=seg;
coun[seg]++;
}
else
{
pre=a[i];
ri[seg]=i-1;
val[++seg]=pre;
coun[seg]++;
le[seg]=i;
id[i]=seg;
}
}
ri[seg]=n;
/*for(int i=1;i<=seg;i++)
cout<<"i="<<i<<" val="<<val[i]<<" coun="<<coun[i]<<" left="<<le[i]<<" right="<<ri[i]<<endl;
cout<<endl;*/
initRMQ(coun);
int l,r;
while(q--)
{
scanf("%d%d",&l,&r);
if(id[l]==id[r])
{
printf("%d\n",r-l+1);
continue;
}
int ans1=rmq(id[l]+1,id[r]-1);//注意范围
int ans2=max(ri[id[l]]-l+1,r-le[id[r]]+1);
printf("%d\n",max(ans1,ans2));
}
}
return 0;
}