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

poj 3368 Frequent values rmq

2013-09-02 16:47 369 查看
题意:给你一串数列,然后给你一个起终位置对,问你这个段序列里出现最多的出现了几次。

思路:一段序列里,无非就是三种情况,1,一组相同的数,2两组相同,3,3组或者更多组数,这样我们队每一组数的开头结束位置记录一下,然后对每次询问判断一下几组数,分别讨论,多组的就分为第一组,最后一组,中间多组,中间直接rmq就可以了。

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <stack>
#define loop(s,i,n) for(i = s;i < n;i++)
#define cl(a,b) memset(a,b,sizeof(a))
int num[100005],b[100005],rt[100005],lt[100005],a[100005],maxd[100005][17];
using namespace std;
void init(int n)
{
int i,j;
for(i = 1;i <= n;i++)
maxd[i][0] = a[i];

for(j = 1;(1<<j) <= n;j++)
{
for(i = 1;i+(1<<j)-1<=n;i++)
{
maxd[i][j] = max(maxd[i][j-1],maxd[i+(1<<(j-1))][j-1]);
}
}
}
int maxrmq(int l,int r)
{
int k = 0;
while(1<<(k+1) <= r-l+1)k++;
return max(maxd[l][k],maxd[r-(1<<k)+1][k]);

}
int main()
{
int n,q;

while(scanf("%d",&n)&&n)
{
int i,j;
scanf("%d",&q);
loop(1,i,n+1)
{
scanf("%d",&b[i]);
}
int cnt,leap;
cnt = 1;
leap = b[1];
for(i = 0;i <= n;i++)
a[i] = num[i] = 0;
lt[1] = 1;
for(i = 1;i <= n;i++)
{
if(leap != b[i])
rt[cnt] = i-1,cnt++,lt[cnt] = i,leap = b[i];
num[i] = cnt;
a[cnt]++;
}
rt[cnt] = n;
init(cnt);

while(q--)
{
int l,r,a,b,c;
scanf("%d %d",&l,&r);
if(num[l] == num[r])
b = r-l+1;
else if(num[r]-num[l] > 1)
{
a = rt[num[l]]-l+1;
b = r-lt[num[r]]+1;
c = maxrmq(num[l]+1,num[r]-1);
b = max(a,b);
b = max(b,c);
}
else
{
a = rt[num[l]]-l+1;
b = r-lt[num[r]]+1;
b = max(a,b);
}

printf("%d\n",b);
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: