題目鏈接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);
}
}
}