莫队

区间出现次数最多元素的出现次数。

直接跑莫队,开桶记录值 $i$ 的出现次数 $w_i$ 和出现次数 $w_i$ 的出现次数 $s_{w_i}$。

如果当前值的出现次数比答案 $ans$ 更大,更新答案。删除元素时更新序列如果 $s_{ans} = 0$ 则令 $ans \leftarrow ans-1$,由于此次删除使得 $ans$ 减少,被删除的数的出现次数必定为 $ans - 1$

注意元素取值可以为负,先行将输入数据加上 $10^5$ 以保证所有数字不小于 $0$

块长取 $\dfrac{n}{\sqrt{q}}$ 等级,固定其为 $250$。总体时间复杂度 $O(n \sqrt{q})$。

#include<bits/stdc++.h>
using namespace std;
constexpr int B=250,ext=100'000;
struct Query{int i,l,r;};
int n,q,l,r,cnt,a[100'005],s[100'005],w[200'005],ans[200'005];
inline void add(int x){
    --s[w[x]],++w[x],++s[w[x]];
    if(w[x]>cnt) ++cnt;
}
inline void del(int x){
    --s[w[x]],--w[x],++s[w[x]];
    if(s[cnt]==0) --cnt;
}
int main(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) a[i]+=ext;
    vector<Query> v(q);
    for(auto &[i,l,r]:v) i=++cnt,scanf("%d%d",&l,&r);
    sort(v.begin(),v.end(),[](auto x,auto y){
        if(x.l/B!=y.l/B) return x.l<y.l;
        return (x.l/B)&1 ? x.r>y.r:x.r<y.r;
    });
    l=1,r=0,cnt=0;
    for(auto [i,ql,qr]:v){
        while(l>ql) add(a[--l]);
        while(r<qr) add(a[++r]);
        while(l<ql) del(a[l++]);
        while(r>qr) del(a[r--]);
        ans[i]=cnt;
    }
    for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
    return 0;
}
最后修改:2024 年 11 月 08 日
如果觉得我的文章对你有用,请随意赞赏