「ZJOI2022」眾數
阿新 • • 發佈:2022-05-08
顯然只有原序列中的數有可能成為答案
於是離散化之後每個數獨立,列舉每個數
這種問題可以考慮根號分治
- \(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; }