POJ 3368 Frequent values(RMQ 区间出现频率最多数字次数)
2013-07-31 10:05
591 查看
题目链接:http://poj.org/problem?id=3368
题意:给定n个升序数组,然后输入查询区间,要求输出这个区间内相同数字的最大个数
解题思路:RMQ算法
其实这个题目想到怎么用RMQ算法就基本上搞定了,如果想不到那么就要费事一点了
其实这个题目难点在于输入的查询区间不固定,有可能一串相连的的相同数字的被查询区间分割开了
那么这样就比较麻烦了,处理起来也比较费事,可是稍微想一下,可以把一个查询分开成
两个部分来查询,一个是前面部分被分割的部分,一个是后面的部分
在用RMQ初始化之间我们先做了一个预处理,就是这样:
for(i=2;i<=n;i++)
{
if(rec[i]==rec[i-1])
tim[i].num=tim[i-1].num+1;
else
{
for(k=i-tim[i-1].num;k<i;k++)
tim[k].fast=i-1;
tim[i].num=1;
}
}也就是当前字符前面出现多少次,注意是前面出现多少次,计算出来,然后再回去把前面的出现字符相同的位置记录出最后一个相同字符出现的位置的标号
接下来就是对tim数组的num进行RMP初始化,完成之后查询
if(b<=tim[a].fast)
printf("%d\n",query(a,b)-tim[a].num+1);
else
printf("%d\n",MAX(query(a,tim[a].fast)-tim[a].num+1,query(tim[a].fast+1,b)));查询是上面一段代码,如果右边的(a,b)这个区间一直都是一个数字,那么直接查询区间(a,b)然后减去在到a的时候这个数字已经出现的次数
完了之后就是分开两个区间查询,一个是左边区间到和一直数字相等的位置,然后就是后面的到b,两者取较大的就OK 了!
#include <stdio.h>
#include <string.h>
题意:给定n个升序数组,然后输入查询区间,要求输出这个区间内相同数字的最大个数
解题思路:RMQ算法
其实这个题目想到怎么用RMQ算法就基本上搞定了,如果想不到那么就要费事一点了
其实这个题目难点在于输入的查询区间不固定,有可能一串相连的的相同数字的被查询区间分割开了
那么这样就比较麻烦了,处理起来也比较费事,可是稍微想一下,可以把一个查询分开成
两个部分来查询,一个是前面部分被分割的部分,一个是后面的部分
在用RMQ初始化之间我们先做了一个预处理,就是这样:
for(i=2;i<=n;i++)
{
if(rec[i]==rec[i-1])
tim[i].num=tim[i-1].num+1;
else
{
for(k=i-tim[i-1].num;k<i;k++)
tim[k].fast=i-1;
tim[i].num=1;
}
}也就是当前字符前面出现多少次,注意是前面出现多少次,计算出来,然后再回去把前面的出现字符相同的位置记录出最后一个相同字符出现的位置的标号
接下来就是对tim数组的num进行RMP初始化,完成之后查询
if(b<=tim[a].fast)
printf("%d\n",query(a,b)-tim[a].num+1);
else
printf("%d\n",MAX(query(a,tim[a].fast)-tim[a].num+1,query(tim[a].fast+1,b)));查询是上面一段代码,如果右边的(a,b)这个区间一直都是一个数字,那么直接查询区间(a,b)然后减去在到a的时候这个数字已经出现的次数
完了之后就是分开两个区间查询,一个是左边区间到和一直数字相等的位置,然后就是后面的到b,两者取较大的就OK 了!
#include <stdio.h>
#include <string.h>
#include <iostream> #include <cmath> #include <algorithm> using namespace std; #define maxn 210000 #define MAX(a,b) (a>b?a:b) int rec[maxn]; //int tim[maxn]; struct node { int num; int fast; }tim[maxn]; int map[maxn][20]; int n,m; int init_rmq(int len) { int i,j,k; for(i=1;i<=len;i++) map[i][0]=tim[i].num; for(j=1;j<20;j++) for(i=1;i<=len && ((1<<(j-1))+i)<=len;i++) { map[i][j]=MAX(map[i][j-1],map[i+(1<<(j-1))][j-1]); } return 0; } int query(int L,int R) { int k=int(log(double(R-L+1))/log(2.0)); return MAX(map[L][k],map[R-(1<<k)+1][k]); } int main() { int i,j,k; int a,b; while(scanf("%d",&n),n) { scanf("%d",&m); for(i=1;i<=n;i++) scanf("%d",&rec[i]); k=1; tim[1].num=1; for(i=2;i<=n;i++) { if(rec[i]==rec[i-1]) tim[i].num=tim[i-1].num+1; else { for(k=i-tim[i-1].num;k<i;k++) tim[k].fast=i-1; tim[i].num=1; } } for(k=i-tim[i-1].num;k<i;k++) tim[k].fast=i-1; init_rmq(n); for(i=0;i<m;i++) { scanf("%d%d",&a,&b); if(b<=tim[a].fast) printf("%d\n",query(a,b)-tim[a].num+1); else printf("%d\n",MAX(query(a,tim[a].fast)-tim[a].num+1,query(tim[a].fast+1,b))); } //for(i=0;i<=n;i++) //printf("%d %d\n",tim[i].num,tim[i].fast); } return 0; }
相关文章推荐
- POJ 3368 Frequent values(RMQ 求区间出现最多次数的数字的次数)
- POJ 3368 Frequent values(RMQ 求区间出现最多次数的数字的次数)
- 【POJ 3368】【RMQ 或者 线段树】Frequent values【求出区间内连续出现次数最多的数的次数。】
- poj 3368 RMQ(查询给定区间内频率最多的数字数量)
- poj 3368 统计区间出现次数最多数个数 RMQ
- UVA 11235 Frequent values 非递减序列 l r范围内 出现最多的数字次数 RMQ
- poj 3368 RMQ 求最多出现次数的数
- POJ 3368—— Frequent values(频繁出现的数值UVA11235) RMQ
- (POJ3368)Frequent values <RMQ 求区间出现次数最多的数出现的次数>
- (POJ3368)Frequent values <RMQ 求区间出现次数最多的数出现的次数>
- hdu 1806 Frequent values(给定一个非降序数组,求任意区间内出现次数最多的数的次数)
- POJ 3368 区间数字出现最多次数
- (Realx 数论1.28)POJ 2282 The Counting Problem(区间统计数字:统计a、b之间各个数字(0~9)出现的次数)
- POJ 3368 线段树,给定区间求连续不降序列的在该区间内出现最多的数
- 一个简单的实现找出数组中一个数字出现次数最多的数字的算法
- 【POJ】3368-Frequent values(RMQ或线段树)
- noip2010 数字统计 (统计某一数字区间中,2出现的次数)
- PHP统计数值数组中出现频率最多的10个数字的方法
- 一个简单的算法---实现找出数组中一个数字出现次数最多的数字
- 由自然数1-1000中某些数字,找出出现次数最多的数字