因为整个数组是非降序的,所以相同的数字一定是连续的
对于每次询问(X,Y) 可分为(X, R[X]),(R[X]+1,L[Y]-1),(L[Y],Y)三部分求解
其中易得(X,R[X]) = R[X]-X+1, (L[Y],Y)= Y-L[Y]+1;
可用conut【i】记录每个元素A[i]出现的次数,因为(R[X]+1,L[Y]-1)中的每个元素的所有部分都在该区间内,所以(R[X]+1,L[Y]-1)=max{count【i】| R[X]+1<=i <= L[Y]-1}
不过之间的位运算有个地方没注意,然后RE了。。。
代码:
#include <stdio.h>
#include <string.h>
#define maxn 100000
int a[maxn+5];
int R[maxn+5]; //下标为i的右端点
int L[maxn+5];// 左端点
int count[maxn+5]; //i的右端点减去左端点
int dp[maxn+5][20]; //以i为起点,2^j长度的count的最大值
int max(int a, int b)
{
return a> b? a: b;
}
int main()
{
int n, q;
while(scanf("%d",&n)!=EOF && n)
{
scanf("%d",&q);
for(int i= 1; i<= n; i++)
scanf("%d",&a[i]);
L[1]= 1;
R[1]= 1;
for(int i= 2; i<= n; i++)
if(a[i]== a[i-1])
{
L[i]= L[i-1];
R[i]= R[i-1]+1;
}
else
{
L[i]= R[i]= i;
}
for(int i= n-1; i>= 1; i--)
if(L[i]== L[i+1])
R[i]= R[i+1];
for(int i= 1; i<= n; i++)
count[i]= R[i]- L[i]+ 1;
for(int i= 1; i<= n; i++)
dp[i][0]= count[i];
for(int j= 1; (1<<j) <= n; j++)
for(int i= 1; (i-1)+(1<<j)<= n; i++)
dp[i][j]= max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
//dp[i][j]= max(dp[i][j-1], dp[i+1<<(j-1)][j-1]); 我之前是这样写的,然后就RE了。
while(q--)
{
int x, y;
scanf("%d %d",&x,&y);
if(L[x] == L[y])
printf("%d\n",y-x+1);
else if(R[x]+1==L[y])
printf("%d\n",max(R[x]-x+1,y-L[y]+1));
else
{
int ans;
int k= 0;
int l= R[x]+ 1;
int r= L[y]- 1;
while((1<<k+1) <= r-l+1)
k++;
ans= max(dp[l][k], dp[r-(1<<k)+1][k]);
ans= max(ans, R[x]- x+ 1);
ans= max(ans, y- L[y]+ 1);
printf("%d\n",ans);
}
}
}
return 0;
}