「ZJOI2022」众数
作者:互联网
显然只有原序列中的数有可能成为答案
于是离散化之后每个数独立,枚举每个数
这种问题可以考虑根号分治
- \(c_i>B\),我们可以枚举中间那一段的颜色变成了什么,复杂度 \(O(n)\)
- \(c_i\leq B\),如果中间那一段的 \(c_j>B\),可以在 \(j\) 处类似上面那种方法处理一下,否则中间这一段最多 \(B\) 步,直接预处理 \(f[i][j]\) 表示 \(i\) 出发走 \(j\) 步最近走到哪,复杂度 \(O(cB)\)
于是 \(O(n\sqrt n)\)
#include <bits/stdc++.h>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
const int N=2e5+5;
const int M=505;
typedef long long ll;
typedef double db;
# define chkmax(a,b) a=max(a,b)
# define chkmin(a,b) a=min(a,b)
# define PII pair<int,int>
# define mkp make_pair
template<typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int TT,n,m,B;
int a[N],b[N],p[N],tot;
int f[N][M],g[N];
vector<int> T[N];
int siz[N];
int ans1;
int out[N],ans2;
bool vis[N];
void check(int val,int i){
if(ans1<val){
Rep(j,1,ans2)vis[out[j]]=false;
ans1=val,out[ans2=1]=i;
vis[i]=true;
}
else if(ans1==val&&!vis[i])out[++ans2]=i,vis[i]=true;
}
namespace force{
void solve(int x){
int res=0;
for(int i=-1;i<siz[x];i++){
int now=max(i,0),p=i==-1?0:T[x][i];
Rep(j,1,B){
if(f[p][j]>n)break;
while(now<siz[x]&&T[x][now]<=f[p][j])now++;
chkmax(res,i+1+j+siz[x]-now);
}
}
check(res,x);
}
}
namespace ecrof{
void solve(int x){
Rep(i,1,n)g[i]=0;
for(int i=0;i<siz[x];i++)g[T[x][i]]++;
Rep(i,1,n)g[i]+=g[i-1];
int res=0;
Rep(i,1,m){
if(i==x)continue;
int mn=0;
for(int j=0;j<siz[i];j++){
chkmin(mn,j-g[T[i][j]-1]);
chkmax(res,j+1-g[T[i][j]]-mn);
}
if(siz[i]<B){
int mx=0,allmax=0;
for(int j=0;j<siz[i];j++){
chkmax(allmax,siz[i]-j+g[T[i][j]-1]+mx);
chkmax(mx,j+1-g[T[i][j]]);
}
check(allmax,i);
}
}
res+=siz[x];
check(res,x);
}
}
int main()
{
# ifndef ONLINE_JUDGE
freopen("testdata.in","r",stdin);
//freopen("test1.out","w",stdout);
# endif
read(TT);
while(TT--){
tot=0;
read(n),B=sqrt(n)+1;
Rep(i,1,n)read(a[i]),b[i]=a[i];
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-b-1;
Rep(i,1,n)a[i]=lower_bound(b+1,b+m+1,a[i])-b;
Rep(i,1,n)siz[a[i]]++;
Rep(i,1,m)if(siz[i]>=B)p[++tot]=i;
Rep(i,1,n)T[a[i]].push_back(i);
Rep(j,1,B)f[n][j]=1e9;
_Rep(i,n-1,0){
Rep(j,1,B)f[i][j]=f[i+1][j];
if(siz[a[i+1]]>=B)continue;
int now=lower_bound(T[a[i+1]].begin(),T[a[i+1]].end(),i)-T[a[i+1]].begin();
for(int j=now;j<siz[a[i+1]];j++)chkmin(f[i][j-now+1],T[a[i+1]][j]);
}
ans1=ans2=0;
Rep(i,1,m){
int val=0;
if(siz[i]<B)force::solve(i);
else ecrof::solve(i);
}
printf("%d\n",ans1);
sort(out+1,out+ans2+1);
Rep(i,1,ans2)printf("%d\n",b[out[i]]);
Rep(i,1,m)T[i].clear(),siz[i]=0,vis[i]=false;
}
return 0;
}
标签:typedef,int,Rep,getchar,众数,ZJOI2022,now,define 来源: https://www.cnblogs.com/devout/p/16246343.html