您的位置:首页 > 产品设计 > UI/UE

UVA11235 Frequent values(RMQ)

2018-03-09 21:04 459 查看
题目大意:给出一个升序的序列,对于一系列的询问(i,j),回答i到j中出现次数最多的数字。

白书上的例题QAQ,游程编码建立对应的序号与段与最远到达的区间的序号,用RMQ查询一下即可。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
const int N=100005;
int val
;//第i段的值
int data
;
int countt
,num
,left
,right
;//第i段的次数 位置p所在的段数 位置p所在段的左右端点
int rmq
[50];

void makermq(int n)
{
for(int i=1;i<=n;i++)
rmq[i][0]=countt[i];

for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<(j-1))<=n;i++)
rmq[i][j]=max(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]);
}
int query(int l,int r)
{
int k=log2(r-l+1);
return max(rmq[l][k],rmq[r-(1<<k)+1][k]);
}
int main()
{
int n,q;
while(scanf("%d",&n)!=EOF&&n)
{
scanf("%d",&q);
for(int i=1;i<=n;i++)
scanf("%d",&data[i]);
int tot=1;
int res=1;

val[1]=data[1];
num[1]=1;

for(int i=2;i<=n;i++)
{
if(data[i]!=val[tot])
{
countt[tot]=res;
val[++tot]=data[i];
res=1;
}
else
res++;

if(i==n&&data[i]==data[i-1])
{
countt[tot]=++res;
num[i]=tot;
}
num[i]=tot;
}
/*
for(int i=1;i<=tot;i++)
printf("%d %d %d\n",val[i],countt[i],num[i]);

for(int i=1;i<=n;i++)
printf("num=%d\n",num[i]);
*/
left[1]=1;
for(int i=2;i<=n;i++)
{
if(data[i]!=data[i-1])
left[i]=i;
else
left[i]=left[i-1];
}

right
=n;
for(int i=n-1;i>=1;i--)
{
if(data[i]!=data[i+1])
right[i]=i;
else
right[i]=right[i+1];
}
/*
for(int i=1;i<=n;i++)
printf("%d %d\n",left[i],right[i]);
*/
makermq(tot);
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
if(val[num[l]]==val[num[r]])
{
printf("%d\n",r-l+1);
}
else if(num[l]+1==num[r])
{
int ans1=right[l]-l+1;
int ans2=r-left[r]+1;
printf("%d\n",max(ans1,ans2));
}
else
{
int ans1=right[l]-l+1;
int ans2=r-left[r]+1;
int ans3=query(num[l]+1,num[r]-1);
//printf("%d %d\n",num[l]+1,num[r]-1);
//printf("%d %d %d\n",ans1,ans2,ans3);
printf("%d\n",max(max(ans1,ans2),ans3));
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: