题目
给定一个长度为 (n) 的序列 (a),请将其重新排序,
新序列中任意相邻两个数之和都不能被 (3) 整除。
分析
分类讨论,如果只有3的倍数多于1个无解
没有 (3k+1) 或者没有 (3k+2) 很好做直接穿插
没有3的倍数如果同时存在 (3k+1) 和 (3k+2) 无解
否则 (3k,3k+1,3k+2) 均有
考虑 (3k+1,3k+2) 分开放,那么必须有一个(3k)放在两个中间,
然后由于(3k)不能相邻,那么直接穿插,如果还有剩余就是无解
代码
#include <cstdio>
#include <cctype>
#include <vector>
#define rr register
using namespace std;
vector<int>K[3]; int n,m0,m1,m2;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
signed main(){
n=iut();
for (rr int i=1;i<=n;++i){
rr int x=iut();
K[x%3].push_back(x);
}
m0=K[0].size(),m1=K[1].size(),m2=K[2].size();
if (m1&&m2){
if (m0>m1+m2+1||m0<1) return !printf("No
");
printf("Yes
");
for (rr int i=0;i<m1;++i){
if (m0>1) printf("%d ",K[0][m0-1]),--m0;
printf("%d ",K[1][i]);
}
printf("%d ",K[0][m0-1]),--m0;
for (rr int i=0;i<m2;++i){
printf("%d ",K[2][i]);
if (m0) printf("%d ",K[0][m0-1]),--m0;
}
return 0;
}
if (!m1&&!m2){
if (m0==1) return !printf("Yes
%d",K[0][0]);
else return !printf("No
");
}
if (m1){
if (m0>m1+1) return !printf("No
");
printf("Yes
");
for (rr int i=0;i<m1;++i){
if (m0) printf("%d ",K[0][m0-1]),--m0;
printf("%d ",K[1][i]);
}
if (m0) printf("%d ",K[0][m0-1]),--m0;
}
if (m2){
if (m0>m2+1) return !printf("No
");
printf("Yes
");
for (rr int i=0;i<m2;++i){
if (m0) printf("%d ",K[0][m0-1]),--m0;
printf("%d ",K[2][i]);
}
if (m0) printf("%d ",K[0][m0-1]),--m0;
}
return 0;
}