「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;
}
posted @ 2022-05-08 18:19  YuukiYumesaki  阅读(34)  评论(0编辑  收藏  举报