#构造#洛谷 6470 [COCI2008-2009#6]CUSKIJA

题目

给定一个长度为 \(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\n");
	    printf("Yes\n");
	    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\n%d",K[0][0]);
		    else return !printf("No\n");
	}
	if (m1){
		if (m0>m1+1) return !printf("No\n");
		printf("Yes\n");
		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\n");
		printf("Yes\n");
		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;
} 
posted @ 2020-11-03 16:23  lemondinosaur  阅读(66)  评论(0编辑  收藏  举报