题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1806
题目大意:
给你一组非递减的数列,询问在a,b的区间中出现次数最多的数的次数。
输入
10 3
-1 -1 1 1 1 1 3 10 10 102 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);
}
}
}