比赛最后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;
}