poj3368 RMQ
题目大意说给出一系列数,这列数是不降的,然后任意给出一个区间[i,j],让你求出那个重复次数最多的数的出现次数。由于给出的查询次数很多,我就考虑用RMQ来解,但是这个不能直接套用模板,因为加入我们对区间[i,j]进行查询,如果从k处分开取两边区间的最大的重复次数是不一定正确的,因为分开的那个地方可能把实际重复次数最多的那个数一分为二,这样求出的就不是最大的了,所以只需要多加一个判断,从分开出往左往右循环找到最大的重复次数,看这个数是否大于我们当前得到的那个数(这个数是取左右区间的最大值)。
代码如下:
#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
const int N=100001;
int a[N];
struct node{
int num,cnt;
};
node m[N][18];
void initrmq(int n)
{
int i,j;
for(i=0;i<n;i++)
m[i][0].cnt=1;
for(j=1;(1<<j)<=n;j++)
{
for(i=0;i+(1<<j)-1<n;i++)
{
if(m[i][j-1].cnt > m[i+(1<<(j-1))][j-1].cnt)
m[i][j].cnt=m[i][j-1].cnt;
else
m[i][j].cnt=m[i+(1<<(j-1))][j-1].cnt;
//多一个判断,看断开的那个数是否是重复次数最多的
int tmp=a[i+(1<<(j-1))-1];
int x=i+(1<<(j-1))-1,y=x,r=i+(1<<j)-1;
while(x>=i && (a[x]==tmp))
x--;
while(y<=r && (a[y]==tmp))
y++;
int tmpcnt=y-x-1;
if(tmpcnt > m[i][j].cnt)
{
m[i][j].cnt=tmpcnt;
}
}
}
}
int queryrmq(int i,int j)
{
int k=(int)(log((j-i+1)*1.0)/(log(2.0))),rscnt;
if(m[i][k].cnt < m[j-(1<<k)+1][k].cnt)
rscnt=m[j-(1<<k)+1][k].cnt;
else
rscnt=m[i][k].cnt;
int tmp=a[i+(1<<k)-1];
// cout<<rscnt<<" idx "<<k<<"分开的idx"<<i+(1<<k)-1<<" "<<tmp<<endl;
int x=i+(1<<k)-1,y=x;
while(x>=i && (a[x]==tmp))
x--;
while(y<=j && (a[y]==tmp))
y++;
int tmpcnt=y-x-1;
// cout<<"new "<<y<<" "<<x<<" "<<tmpcnt<<endl;
if(tmpcnt > rscnt)
rscnt=tmpcnt;
return rscnt;
}
int main()
{
int n,q,i,ans,l,r;
while(1)
{
scanf("%d",&n);
if(!n)
break;
scanf("%d",&q);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
initrmq(n);
while(q--)
{
scanf("%d%d",&l,&r);
ans=queryrmq(l-1,r-1);
printf("%d\n",ans);
}
}
return 0;
}
posted on 2011-09-17 18:04 buptLizer 阅读(1107) 评论(0) 编辑 收藏 举报