题解 P8330 [ZJOI2022] 众数
众所周知,ZJOI 的签到题一般在 D1T2。
没去 ZJOI,在家口胡的。想了一会似乎就会根号做法了。真难受没得去省选,本来可能会是考场上做出的第一个黑吧。
原题是选择一段区间 ,使得 内的众数次数与除去此段区间外的众数次数的和最大,此时众数答案是 外的任何一个众数。
根号分治。设 。考虑颜色出现次数不超过 的是 A 类,否则是 B 类。我们枚举一下 外的众数是 。
- 内部的众数是 A 类。此时内部的众数次数必然不超过 。
枚举内部众数出现次数 ,此时只要让 内答案是 且 的出现次数最小就行了。对于每个 ,预处理好位置 的颜色的之前第 个出现位置 。考虑所有相邻 的位置之间的间隔,找到这里 的最大值就行了。然后用双指针找一下当前 的最大值位于哪个间隔,就可以计算。
- 内部的众数是 B 类。此时内部的众数种类不超过 。
枚举当前内部众数是 。假设每个 是 ,每个 是 ,目标是找到 使得 最大。所以 必然落在 上,前缀和一下可以用 的次数次检查完成。
总复杂度 。
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N=2e5+5,B=447;
struct point
{
int x,id;
}b[N];
int a[N],ans[N],c[N],col[N],pre[N],d[N];
int A[N],C[N],cnta,cntc,sum[N];
vector<int>g[N];
bool cmp(point x,point y)
{
return x.x<y.x;
}
inline int read()
{
char C=getchar();
int F=1,ANS=0;
while (C<'0'||C>'9')
{
if (C=='-') F=-1;
C=getchar();
}
while (C>='0'&&C<='9')
{
ANS=ANS*10+C-'0';
C=getchar();
}
return F*ANS;
}
void work()
{
n=read();
for (int i=1;i<=n;i++) b[i].id=i,b[i].x=read();
sort(b+1,b+n+1,cmp);
m=0;
int gp=0;
for (int i=1;i<=n;i++)
{
if (i==1||b[i].x!=b[i-1].x) c[++m]=b[i].x;
a[b[i].id]=m;
}
for (int i=1;i<=m;i++) ans[i]=0,col[i]=0;
for (int i=1;i<=m;i++) g[i].clear();
for (int i=1;i<=n;i++) col[a[i]]++,g[a[i]].push_back(i),d[i]=col[a[i]];
cnta=0,cntc=0;
int b=0;
for (int i=1;i<=m;i++)
{
gp=max(gp,col[i]);
if (col[i]>B) A[++cnta]=i;
else C[++cntc]=i,b=max(b,col[i]);
}
for (int j=1;j<=cnta;j++)
{
int v=A[j];
for (int i=1;i<=n;i++) sum[i]=0;
for (int i:g[v]) sum[i]=-1;
for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
for (int u=1;u<=m;u++)
{
int res=0,tot=0;
for (int i:g[u])
{
ans[u]=max(ans[u],col[v]+col[u]-res+sum[n]-sum[i-1]+tot);
res++;
tot=max(tot,res+sum[i]);
}
ans[u]=max(ans[u],tot+col[v]);
}
}
int res=0;
for (int i=1;i<=m;i++) res=max(res,ans[i]);
for (int k=1;k<=b;k++)
{
if (k+gp<res) continue;
pre[0]=-1;
for (int i=1;i<=n;i++)
{
if (d[i]-k<=-1) pre[i]=-1;
else pre[i]=g[a[i]][d[i]-k];
}
for (int i=2;i<=n;i++) pre[i]=max(pre[i-1],pre[i]);
for (int u=1;u<=m;u++)
{
int res=0,tot=0;
for (int i:g[u])
{
int p=pre[i-1];
if (p==-1)
{
res++;
continue;
}
while (tot<col[u]&&p>g[u][tot]) tot++;
ans[u]=max(ans[u],k+col[u]-(res-tot));
res++;
}
if (pre[n]!=-1)
{
int p=pre[n];
while (tot<col[u]&&p>g[u][tot]) tot++;
ans[u]=max(ans[u],k+col[u]-(res-tot));
}
}
}
for (int i=1;i<=m;i++) res=max(res,ans[i]);
printf("%d\n",res);
for (int i=1;i<=m;i++)
{
if (ans[i]==res) printf("%d\n",c[i]);
}
}
int main()
{
int T=read();
while (T--) work();
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
2021-06-30 题解 P4025 [PA2014]Bohater