[CF1446D1&D2] Frequency Problem
\(\text{Problem}:\)Easy verson Hard verson
\(\text{Solution}:\)
如果整个序列的众数不唯一,则答案显然为 \(n\)。否则记整个序列的众数为 \(p\),有性质:最长的众数不唯一的子区间内一定有出现过 \(p\),且 \(p\) 一定是该区间的众数之一。证明详见 Duyi's tutorial。
考虑枚举另一个该区间的众数 \(q\),则只需要求出 \(p,q\) 出现次数相等的最长区间即可。这个问题类似于求有多少个区间的和为 \(0\),利用前缀和相等的性质即可解决。时间复杂度 \(O(n\max\{a_{i}\})\),可以通过 \(D1\)。
优化这一过程。考虑区间众数的在区间内的出现次数,这类与某个数出现次数的问题通常可以用根号分治的思想进行解决。如果一个数出现次数大于等于 \(B\),可以用 \(D1\) 的做法解决。则剩余可能成为答案的区间众数的出现次数小于 \(B\),可以暴力枚举这个出现次数,用双指针解决这个问题。时间复杂度 \(O(\cfrac{n^2}{B}+nB)\),当 \(B=\sqrt n\) 时,时间复杂度为 \(O(n\sqrt n)\),可以通过 \(D2\)。
\(\text{Code}:\)
#include <bits/stdc++.h>
#pragma GCC optimize(3)
#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
using namespace std; const int N=400010, B=303;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
int n,Ans,a[N],book[N],mxd,pp,qz1[N],qz2[N],F[N],g[N],cnt[N];
vector<int> A;
inline void Add(int x)
{
cnt[g[a[x]]]--;
g[a[x]]++;
cnt[g[a[x]]]++;
}
inline void Del(int x)
{
cnt[g[a[x]]]--;
g[a[x]]--;
cnt[g[a[x]]]++;
}
signed main()
{
n=read();
for(ri int i=1;i<=n;i++) a[i]=read(), book[a[i]]++, mxd=max(mxd,book[a[i]]);
for(ri int i=1;i<=n;i++)
{
if(book[i]==mxd)
{
if(pp) return printf("%lld\n",n)&0;
pp=i;
}
else if(book[i]>=B) A.eb(i);
}
for(ri int i=1;i<=n;i++) qz1[i]=qz1[i-1]+(a[i]==pp);
for(auto i:A)
{
for(ri int j=1;j<=n;j++) qz2[j]=qz2[j-1]+(a[j]==i);
for(ri int j=0;j<=n+n;j++) F[j]=n+1;
for(ri int j=1;j<=n;j++)
{
Ans=max(Ans,j-F[qz2[j]-qz1[j]+n]+1);
F[qz2[j-1]-qz1[j-1]+n]=min(F[qz2[j-1]-qz1[j-1]+n],j);
}
}
for(ri int i=1;i<B;i++)
{
int l=1;
for(ri int j=1;j<=n;j++)
{
Add(j);
int tt=g[a[j]];
if(tt>i)
{
while(l<j&&a[l]!=a[j]) Del(l), l++;
Del(l), l++;
}
if(cnt[i]>=2) Ans=max(Ans,j-l+1);
}
while(l<=n) Del(l), l++;
}
printf("%lld\n",Ans);
return 0;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。