区间频率问题 hdu1806

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1806

 

题目大意:

给你一组非递减的数列,询问在a,b的区间中出现次数最多的数的次数。

输入

10 3 
-1  -1  1  1  1  1  3  10  10  10

2 3

1 10

5 10

输出

1

4

3

 解决方法

第一种 RMQ

对原数组统计前缀连续次数

原数组

1 1 1 2 2 3 4 5 6 6

频率数组

1 2 3 1 2 1 1 1 2

对频率数组使用RMQ方法进行处理

查询部分

1.先将查询区间的前缀连续相同的单独计算,

while (num[l]==num[l-1]+1&&l<=b) {
        l++;
        count++;
  }

2.在对去掉已计算的前缀后面部分从dp数组中查询。

int len = b - a + 1;
    if (count == len)return count;
    len = b - l+1;
    int k = log(len*1.0)/log(2.0);
    return max(count,max(dp[k][l], dp[k][b - (1 << k) + 1]));

代码

 

#include<cstdio>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#pragma warning (disable:4996)
using namespace std;
#define inf 0x7fffffff
const int mx = 200005;
typedef long long ll;
int n, m;


int num[mx];
int dp[20][mx];
void st() {
	for (int i = 1; i <= n; i++) {
		dp[0][i] = num[i];
	}
	for (int i = 1; 1 << i <= n; i++) {
		for (int j = 1; j + (1 << i-1) <= n; j++) {
			dp[i][j] = max(dp[i - 1][j], dp[i - 1][j + (1 << i-1)]);
		}
	}
}

int solve(int a,int b) {
	int l = a;
	int count=0;
	while (num[l]==num[l-1]+1&&l<=b) {
		l++;
		count++;
	}
	int len = b - a + 1;
	if (count == len)return count;
	len = b - l+1;
	int k = log(len*1.0)/log(2.0);
	return max(count,max(dp[k][l], dp[k][b - (1 << k) + 1]));

}

int main() {
	while (scanf("%d",&n)&&n) {
		scanf("%d",&m);
		//init();
		int a,pre;
		memset(num, 0, sizeof(num));
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= n; i++) {	
			
			scanf("%d",&a);
			if (i == 1) {
				num[i] = 1;
				pre = a;
			}
			else {
				if (a == pre)
					num[i] = num[i - 1] + 1;
				else {
					num[i] = 1;
					pre = a;
				}
			}
		}
		st();
		for (int i = 0; i < m; i++) {
			int a, b;
			scanf("%d %d", &a, &b);
			int ans = solve(a, b);
			printf("%d\n", ans);
				
		}
	}


}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章