洛谷P3709 大爷的字符串

时间:2023-03-09 15:14:09
洛谷P3709 大爷的字符串

题意:多次求区间众数的出现次数。

解:

这题居然可以莫队......

首先开个桶。然后还要开个数组,cnt[i]表示出现i次的数有多少个。

然后就可以O(1)修改了。

 #include <cstdio>
#include <algorithm>
#include <cmath> inline void read(int &x) {
x = ;
char c = getchar();
while(c < '' || c > '') {
c = getchar();
}
while(c >= '' && c <= '') {
x = (x << ) + (x << ) + c - ;
c = getchar();
}
return;
} const int N = ; int fr[N], a[N], bin[N], cnt[N], ans, X[N]; struct ASK {
int l, r, t, ans;
inline bool operator <(const ASK &w) const {
if(fr[l] != fr[w.l]) {
return fr[l] < fr[w.l];
}
return r < w.r;
}
}ask[N]; inline bool cmp(const ASK &A, const ASK &B) {
return A.t < B.t;
} inline void add(int p) {
cnt[bin[a[p]]]--;
bin[a[p]]++;
cnt[bin[a[p]]]++;
if(bin[a[p]] > ans) {
ans = bin[a[p]];
}
return;
} inline void del(int p) {
cnt[bin[a[p]]]--;
bin[a[p]]--;
cnt[bin[a[p]]]++;
if(!cnt[bin[a[p]] + ] && ans == bin[a[p]] + ) {
ans--;
}
return;
} int main() {
int n, m;
read(n);
read(m);
int T = sqrt(n);
for(int i = ; i <= n; i++) {
read(a[i]);
X[i] = a[i];
fr[i] = (i - ) / T + ;
}
for(int i = ; i <= n; i++) {
read(ask[i].l);
read(ask[i].r);
ask[i].t = i;
}
std::sort(X + , X + n + );
std::sort(ask + , ask + m + );
int temp = std::unique(X + , X + n + ) - X - ;
for(int i = ; i <= n; i++) {
a[i] = std::lower_bound(X + , X + temp + , a[i]) - X;
} int l = , r = ;
ans = ;
bin[a[]]++;
cnt[] = ;
for(int i = ; i <= m; i++) {
while(l > ask[i].l) {
add(--l);
}
while(r < ask[i].r) {
add(++r);
}
while(l < ask[i].l) {
del(l++);
}
while(r > ask[i].r) {
del(r--);
}
ask[i].ans = ans;
} std::sort(ask + , ask + m + , cmp);
for(int i = ; i <= m; i++) {
printf("%d\n", -ask[i].ans);
}
return ;
}

AC代码