RMQ算法简单实现poj 3368 Frequent values

题目就是一个rmq算法的典型应用,关键是将其转化成rmq的形式,因为每个点都是a[i]<=a[i+1]所以对于每一个点记录他的左边与右边,因而可知他的长度(即出现的频率),然后还有一个值记录频率;最后求解是用的很巧妙的方法;

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int max_s = 100007;
int f[25][max_s],hash[max_s],pow2[25],a[max_s];
struct node
{
int l,r;
int num;
}p[max_s];
int n,len;
void init()
{
int i;
p[0].l=p[0].r=0;
p[0].num=1;
hash[0]=0;
len=0;
for(i=1;i<n;i++)
{
if(a[i]==a[i-1])
{
p[len].r=i;
p[len].num++;
}
else
{
len++;
p[len].l=p[len].r=i;
p[len].num=1;
}
hash[i]=len;
}
}
void init_rmq(int len)
{
int i,j;
for(i=0;i<=len;i++)
f[0][i]=p[i].num;
for(i=1;pow2[i]<=len;i++)
{
for(j=0;j+pow2[i-1]<=len;j++)
f[i][j]=max(f[i-1][j],f[i-1][j+pow2[i-1]]);
}
}
int rmq(int s,int e)
{
int k=log(1.0*(e-s+1))/log(2.0);
return max(f[k][s],f[k][e-pow2[k]+1]);
}
int solve(int s,int e)
{
if(hash[s]==hash[e]) return e-s+1;
else if(hash[s]+1==hash[e])
{
int l=p[hash[s]].r-s+1;
int r=e-p[hash[e]].l+1;
return max(l,r);
}
else
{
int l=p[hash[s]].r-s+1;
int r=e-p[hash[e]].l+1;
l = max(l,r);
r=rmq(hash[s]+1,hash[e]-1);
return max(l,r);
}
}
int main()
{
int q,i;
while(scanf("%d",&n),n)
{
scanf("%d",&q);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
init();
for(i=0;i<=20;i++)
pow2[i]=1<<i;
init_rmq(len);
int s,e;
while(q--)
{
scanf("%d%d",&s,&e);
printf("%d\n",solve(s-1,e-1));
}
}
return 0;
}





posted @ 2011-12-04 11:25  E_star  阅读(217)  评论(0编辑  收藏  举报