Frequent values
题意:给出一段非递减序列,问区间里出现最多的值的次数。
思路:可以把相同元素组合起来用二元组表示。
cnt[i]代表第i段连续的长度
num[i]表示第i个位置的数在那一段
lef[i],righ[i]分别表示第i段的左右端点位置
所求的最大值就是
从L到L所在的段的结束处的元素个数:righ[L]-L+1
从R到R所在的段的开始处的元素个数:R-lef[R]+1
中间第num[L]+1段到第num[R]-1段的cnt的最大值(RMQ)
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int val[maxn],cnt[maxn],num[maxn],l[maxn],r[maxn];
int a[maxn];
int d[maxn][50],len;
void RMQ_init(){
for(int i=1;i<=len;i++)
d[i][0]=cnt[i];
for(int j=1;(1<<j)<=len+1;j++)
for(int i=1;i+(1<<j)-1<=len;i++)
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int RMQ(int l,int r){
int k=0;
while((1<<(k+1)<=r-l+1))
k++;
return max(d[l][k],d[r-(1<<k)+1][k]);
}
int main(){
int n,q;
while(~scanf("%d",&n)&&n){
scanf("%d",&q);
len=1;
memset(cnt,0,sizeof(cnt));
scanf("%d",&a[1]);
cnt[len]=1;
num[1]=len;
l[0]=1;
for(int i=2;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]==a[i-1]){
cnt[len]++;
num[i]=len;
}
else{
r[len]=i-1;
len++;
val[len]=a[i];
cnt[len]=1;
num[i]=len;
l[len]=i;
}
}
RMQ_init();
while(q--){
int ql,qr;
scanf("%d%d",&ql,&qr);
if(num[ql]==num[qr])
printf("%d\n",qr-ql+1);
else{
int ans=0;
if(num[ql]+1<=num[qr]-1)
ans=RMQ(num[ql]+1,num[qr]-1);
ans=max(ans,max(r[num[ql]]-ql+1,qr-l[num[qr]]+1));
printf("%d\n",ans);
}
}
}
}