區間頻率問題 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);
				
		}
	}


}

 

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