UVa 11235

RMQ的应用,因为题目给定的数组相同的数字都是在一起,这意味着非常紧凑,借助RMQ,最值只可能有三种情况

  • 频率最高是因为最左边的数
  • 频率最高是因为最右边的数
  • 将整个数组所有相同的数全部放在一个频数数组里面,所询问的区间内完整包含的那些数的频数最值可以利用RMQ来获取
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <cassert>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
#include <unordered_map>
using namespace std;

const int INF= 0x3f3f3f3f;
const int maxn= 1e5+5;

int n, q;
int a[maxn];
int L[maxn], R[maxn], idx[maxn];
int num[maxn];
int dv[maxn][20];
int lg[maxn];

void InitRMQ(int a[], int tot)
{
	lg[0]= -1;
	for (int i= 1; i <= tot; ++i){
		lg[i]= i & (i-1) ? lg[i-1] : lg[i-1]+1;
		dv[i][0]= a[i];
	}

	for (int j= 1; j <= lg[tot]; ++j){
		for (int i= 1; i+(1<<j)-1 <= tot; ++i){
			dv[i][j]= max(dv[i][j-1], dv[i+(1<<(j-1))][j-1]);
		}
	}
}
int RMQ(int l, int r)
{
	if (l > r){
		return 0;
	}
	int k= lg[r-l+1];
	return max(dv[l][k], dv[r+1-(1<<k)][k]);
}
int main(int argc, char const *argv[])
{
	while (~scanf("%d", &n) && n){
		scanf("%d", &q);
		for (int i= 1; i <= n; ++i){
			scanf("%d", a+i);
		}

		int bg= 1, ed= 1;
		int tot= 1;
		for (int i= 1; i <= n; ++i){
			if (a[i] != a[bg]){
				ed= i-1;
				for (int j= bg; j <= ed; ++j){
					R[j]= ed;
				}
				num[tot]= i-bg;
				++tot;
				bg= i;
			}
			L[i]= bg;
			idx[i]= tot;
		}
		ed= n;
		for (int i= bg; i <= n; ++i){
			R[i]= ed;
		}
		num[tot]= n+1-bg;

		InitRMQ(num, tot);

		int ans;
		while (q--){
			scanf("%d%d", &bg, &ed);
			if (idx[bg] == idx[ed]){
				ans= ed-bg+1;
			} else{
				ans= max(R[bg]+1-bg, ed+1-L[ed]);
				ans= max(RMQ(idx[bg]+1, idx[ed]-1), ans);
			}
			printf("%d\n", ans);
		}
	}
	return 0;
}

UVa 11235

上一篇:GO语言的进阶之路-爬虫进阶之路


下一篇:GO语言的进阶之路-面向过程式编程