题意:
给一个非降序排列的整数数组a,你的任务是对于一系列询问(i, j),回答ai,ai+1…aj中次数出现最多的值所出现的次数。
解析:
由于数列是非降序的,所以所有相等的数都会聚集在一起。这样我们就可以把整个数组进行编码。如-1,1,1,2,2,2,4就可以编码成(-1,1),(1,2),(2,3),(4,1)表示(a,b)数组中的a连续出现了b次。
用num[i]表示原数组下表是i的数在编码后的第num[i]段。left[i],right[i]表示第i段的左边界和右边界,用coun[i]表示第i段有conu[i]个相同的数。这样的话每次查询(L, R)就只要计算(right[L]-L+1),(R-left[R]+1)和RMQ(num[L]+1, num[R]-1)这三个值的最大值就可以了。
其中,RMQ是对coun数组进行取件查询的结果。
注意:
如果L和R在同一个区间内的话,那么结果就是(R-L+1)
my code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1000010;
int A[N], id[N], left[N], right[N];
int cnt[N], tot;
struct Interval {
int ll, rr;
};
map<int, Interval> mp;
int dp[N*2][20];
void rmq_init(int n) {
for(int i = 1; i <= n; i++)
dp[i][0] = cnt[i];
for(int k = 1; (1 << k) <= n; k++) {
for(int i = 1; i + (1 << k) - 1 <= n; i++) {
dp[i][k] = max(dp[i][k-1], dp[i+(1<<(k-1))][k-1]);
}
}
}
int rmq(int L, int R) {
if(L > R) return -INF;
int len = R - L + 1, k = 0;
while(1 << (k+1) <= len) k++;
return max(dp[L][k], dp[R-(1<<k)+1][k]);
}
int query(int L, int R) {
if(id[L] == id[R]) return R - L + 1;
int mid = rmq(id[L]+1, id[R]-1);
int ll = right[L] - L + 1;
int rr = R - left[R] + 1;
return max(mid, max(ll, rr));
}
int main() {
int n, q;
while(scanf("%d", &n) != EOF && n) {
scanf("%d", &q);
mp.clear();
A[0] = -INF;
tot = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &A[i]);
if(A[i] != A[i-1]) {
mp[A[i]] = (Interval){i, i};
id[i] = ++tot, left[i] = i;
cnt[tot] = 1;
}else {
mp[A[i]].rr = i;
id[i] = tot, left[i] = mp[A[i]].ll;
cnt[tot]++;
}
}
for(int i = 1; i <= n; i++) right[i] = mp[A[i]].rr;
rmq_init(tot);
int ql, qr;
while(q--) {
scanf("%d%d", &ql, &qr);
printf("%d\n", query(ql, qr));
}
}
return 0;
}
本文介绍了一种高效的方法来处理非降序排列的整数数组,通过编码数组并使用RMQ(Range Maximum Query)技术,快速查询指定范围内元素出现的最大频率。适用于大数据集的实时查询优化。
1261

被折叠的 条评论
为什么被折叠?



