本文共 2310 字,大约阅读时间需要 7 分钟。
在处理离散化与最小众数查询的问题时,常常会遇到大量数据的高效查询需求。本文将详细介绍一种基于离散化的方法,用于快速解决此类问题。
本文的主要思路是利用离散化技术,将原数据映射到一个更小的范围内,从而减少计算复杂度。具体实现中,预处理、块划分与查询优化是关键步骤。
#includeusing namespace std;const int M = 1e5 + 10;int n, block, idx, a[M], bl[M], f[510][510], val[M], cnt[M];vector ve[M];void pre(int x) { // 预处理 cnt[x] = 0; int mx = 0, ans = 0; for (int i = (x - 1) * block + 1; i <= n; ++i) { cnt[a[i]]++; int t = bl[i]; if (cnt[a[i]] > mx || (cnt[a[i]] == mx && val[a[i]] < val[ans])) { ans = a[i]; mx = cnt[a[i]]; } f[x][t] = ans; }}int query(int l, int r, int x) { // 在当前块中查找区间的最小众数 int t = upper_bound(ve[x].begin(), ve[x].end(), r) - lower_bound(ve[x].begin(), ve[x].end(), l); return t;}int solve(int l, int r) { int ans, mx; if (bl[l] == bl[r]) { ans = query(l, r, ans); mx = ans; } else { for (int i = l; i <= min(bl[l] * block, r); ++i) { int t = query(l, r, a[i]); if (t > mx || (t == mx && val[a[i]] < val[ans])) { ans = a[i]; mx = t; } } if (bl[l] != bl[r]) { for (int i = (bl[r] - 1) * block + 1; i <= r; ++i) { int t = query(l, r, a[i]); if (t > mx || (t == mx && val[a[i]] < val[ans])) { ans = a[i]; mx = t; } } } } return ans;}map mp;int main() { int l, r; scanf("%d", &n); block = sqrt(n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); if (!mp[a[i]]) { mp[a[i]] = ++idx; val[idx] = a[i]; } a[i] = mp[a[i]]; ve[a[i]].push_back(i); } for (int i = 1; i <= n; ++i) { bl[i] = (i - 1) / block + 1; } for (int i = 1; i <= n; ++i) { scanf("%d", &l); scanf("%d", &r); if (l > r) swap(l, r); printf("%d\n", val[solve(l, r)]); } return 0;}
预处理阶段:
pre(int x)
函数用于处理每个块,统计每个值的出现次数,并记录最小众数。查询阶段:
query(int l, int r, int x)
函数用于在指定区间内查找最小众数。主处理函数:
solve(int l, int r)
函数根据块划分情况,分别处理完整块和非完整块的查询。离散化与数据准备:
val
数组中,记录每个值的原数据。块划分:
bl
数组将数据划分为多个块,块的大小通过 block = sqrt(n)
计算得到。通过上述实现,可以高效解决离散化与最小众数查询问题,适用于大规模数据处理场景。
转载地址:http://njufk.baihongyu.com/