通用求众数离线做法
当只需要找频数超过一半的区间众数的时候pos
数组维护出现位置
还有一种做法是随机化
CF716Div2 D AC代码
#include <bits/stdc++.h>
#define N 300000
using namespace std;
typedef pair<int, int> pii;
int n, m, maxn, a[N + 5];
struct node {
int l, r, mx, aa;
};
node xds[4 * N+5];
vector<int> pos[N+5];
int cnt(int x, int l, int r) {
int ret = upper_bound(pos[x].begin(), pos[x].end(), r) - lower_bound(pos[x].begin(), pos[x].end(), l);
return ret;
}
void build(int id, int l, int r) {
if(l == r) {
xds[id].l = xds[id].r = l;
xds[id].mx = 1;
xds[id].aa = a[l];
return;
}
int mid = (l + r) >> 1;
build(id * 2, l, mid);
build(id * 2 + 1, mid + 1, r);
xds[id].l = l; xds[id].r = r;
if (cnt(xds[id * 2].aa, l, r) > cnt(xds[id * 2 + 1].aa, l, r)) {
xds[id].mx = cnt(xds[id * 2].aa, l, r);
xds[id].aa= xds[id * 2].aa;
} else {
xds[id].mx = cnt(xds[id * 2 + 1].aa, l, r);
xds[id].aa= xds[id * 2 + 1].aa;
}
}
pii get(int id, int l, int r) {
// (frequency, value)
pii ret, ret2;
int f1 = 0, f2 = 0;
if (l <= xds[id].l && xds[id].r <= r) {
return pii(xds[id].mx, xds[id].aa);
}
int mid = (xds[id].l + xds[id].r) >> 1, rl = max(l, xds[id].l), rr = min(r, xds[id].r);
if (l <= mid) {
ret = get(id * 2, l, r);
f1 = cnt(ret.second, rl, rr);
}
if (r > mid) {
ret2 = get(id * 2 + 1, l, r);
f2 = cnt(ret2.second, rl, rr);
}
if (f1 > f2) {
return pii(f1, ret.second);
} else {
return pii(f2, ret2.second);
}
}
int main() {
int l, r;
cin.sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
pos[a[i]].push_back(i);
}
for (int i = 1; i <= n; i++) {
pos[i].push_back(n + 1);
}
build(1, 1, n);
for (int i = 1; i <= m; i++) {
cin >> l >> r;
pii most = get(1, l, r);
cout << max(1, 2 * most.first - (r - l + 1)) << '\n';
}
return 0;
}