Luogu P3709 大爷的字符串题
阅读理解题
真正题意
求区间众数的出现次数,输出时在前面加个负号
题解
莫队!
用tong[i]
表示数i
出现的次数cnt[i]
表示出现i
次的数有多少个
- 加入一个数时,
ans = max(tong[i], ans)
- 删除一个数时,要注意如果
tong[i] == ans && !cnt[tong[i]]
,需要--ans
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 200010
#define LL long long
using namespace std;
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
int a[MAXN], b[MAXN], tot;
struct zzz {
int l, r, pos;
}q[MAXN];
int blo, tong[MAXN], cnt[MAXN], anss[MAXN];
bool cmp(zzz x, zzz y) {
if(x.l / blo != y.l / blo) return x.l / blo < y.l / blo;
else return x.r < y.r;
}
int main() {
int n = read(), m = read(); blo = sqrt((double)n);
for(int i = 1; i <= n; ++i)
a[i] = b[i] = read();
sort(a+1, a+n+1); tot = unique(a+1, a+n+1) - a - 1;
for(int i = 1; i <= n; ++i) b[i] = lower_bound(a+1, a+tot+1, b[i]) - a;
for(int i = 1; i <= m; ++i)
q[i].l = read(), q[i].r = read(), q[i].pos = i;
sort(q+1, q+m+1, cmp);
int l = 1, r = 0, ans = 0;
for(int i = 1; i <= m; ++i) {
while(l < q[i].l) {
--cnt[tong[b[l]]];
if(tong[b[l]] == ans && !cnt[tong[b[l]]]) --ans;
cnt[--tong[b[l]]]++; ++l;
}
while(r > q[i].r) {
--cnt[tong[b[r]]];
if(tong[b[r]] == ans && !cnt[tong[b[r]]]) --ans;
cnt[--tong[b[r]]]++; --r;
}
while(l > q[i].l) {
--l;
--cnt[tong[b[l]]]; cnt[++tong[b[l]]]++;
ans = max(ans, tong[b[l]]);
}
while(r < q[i].r) {
++r;
--cnt[tong[b[r]]]; cnt[++tong[b[r]]]++;
ans = max(ans, tong[b[r]]);
}
anss[q[i].pos] = ans;
}
for(int i = 1; i <= m; ++i) cout << -anss[i] << endl;
return 0;
}