求调
查看原帖
求调
704275
无名之雾楼主2025/7/29 19:43

比赛最后30min看到题后随手写了一发没过。

大致思路是二分集合大小k,然后发现集合之间大小差距在2以内,所以直接对于每个集合按照数字出现次数从大到小插入。

不知道是假了还是写错了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
    return s*w;
}
inline void out(int x){
    if(x==0){putchar('0');return;}
    int len=0,k1=x,c[10005];
    if(k1<0)k1=-k1,putchar('-');
    while(k1)c[len++]=k1%10+'0',k1/=10;
    while(len--)putchar(c[len]);
}
const int N=2e3+5;
int s[N],a[N][N],S[N],aans[N][N],cnt[N];
bool cmp(int x,int y){
    return cnt[x]>cnt[y];
}
bool check(int x,int n){
    vector<int>sz;sz.push_back(-154);
    int siz=n/2/x*2,left=n-siz*x;
    for(int i=1;i<=x;i++){
        if(left)sz.push_back(siz+2),left-=2;
        else sz.push_back(siz);
    }int p=1,q=1;
    for(int i=1;i<=x;i++){
        for(int j=1;j<=sz[i];j++){
            a[i][j]=0;
        }
    }
    for(int i=1;i<=n;i++){
        a[p][q]=s[i];
        if(a[p][q]==a[p][q-1])return 0;
        if(n==i)break;
        do{
            p++;if(p>x)p=1,q++;
        }while(sz[p]<q);
        //cout<<x<<" "<<i<<" "<<p<<" "<<q<<"\n";
    }
    for(int i=1;i<=x;i++)S[i]=sz[i];
    for(int i=1;i<=x;i++){
        for(int j=1;j<=sz[i];j++){
            aans[i][j]=a[i][j];
        }
    }return 1;
}
signed main(){
    int t=read();
    while(t--){
        int n=read(),l=1,r=n,ans=-1;
        memset(cnt,0,sizeof cnt);
        for(int i=1;i<=n;i++)s[i]=read(),cnt[s[i]]++;
        if(n&1){puts("-1");continue;}
        sort(s+1,s+n+1,cmp);
        while(l<=r){
            int mid=l+r>>1;
            if(check(mid,n))r=mid-1,ans=mid;
            else l=mid+1;
        }cout<<ans<<"\n";
        for(int i=1;i<=ans;i++){
            cout<<S[i]<<" ";
            for(int j=1;j<=S[i];j++)cout<<aans[i][j]<<" ";
            puts("");
        }
    }
    return 0;
}
2025/7/29 19:43
加载中...