[USACO08MAR]珍珠配对Pearl Pairing 题解
这题有点像脑筋急转弯,想通了就很简单
题目大意:
\(N\) 个元素(\(N\) 为偶数),需要你来染色。现在需要两个元素为一组,且每一组的元素颜色要保证不同,求任意一种解法。
题意分析:
其实我们来看看,为了保证有解,即有一种方案使得 两个元素为一组,且每一组的元素颜色要保证不同 ,所以 不可能有某种珍珠会超过总数的一半 (否则根据小奥,一定会有两个相同颜色的元素在一组)。
且我们知道: 一共有 \(N\) / 2 组
这个就是抽屉问题(鸟巢问题),想明白了就很简单。
具体操作:
题目给的是每种颜色的数量,我们不妨将 每种颜色的元素数量 转化为 每个元素的颜色。
根据小奥,我们一般做抽屉问题时都是按照 将每种颜色的珍珠按照每组一个 的方式操作。
然后为了正解,我们可以先按照 每种颜色的元素数量 从大到小排序,那么由于不可能有某种珍珠会超过总数的一半,所以即便元素数量最多的颜色的那些元素,排完序后也不可能有一个元素超过中点。
故我们不妨将 第 \(i\) 个元素与 第 \(i + (n / 2)\) 个元素合成一组,这样可以方便而快速的避免无解。
数据太水,不排序也能过,博主太懒,也把排序略了。
AC代码在此镇楼:
#include<bits/stdc++.h>
#include<cctype>
#pragma GCC optimize(2)
#define in(n) n = read()
#define out(a) write(a)
#define outn(a) out(a),putchar('\n')
#define Min(a,b) a < b ? a : b
#define Max(a,b) a > b ? a : b
#define ll long long
#define New ll
#define rg register
using namespace std;
namespace IO_Optimization
{
inline New read()//快读
{
New X = 0,w = 0;
char ch = 0;
while(!isdigit(ch))
{
w |= ch == '-';
ch=getchar();
}
while(isdigit(ch))
{
X = (X << 3) + (X << 1) + (ch ^ 48);
ch = getchar();
}
return w ? -X : X;
}
inline void write(long long x)//快输
{
if(x < 0) putchar('-'),x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO_Optimization;
const int MAXN = 100000 + 2;//定义常量
int s[MAXN]; //记录每个珍珠的颜色
int n,c,k;//如题,k为输入时当前有了多少珍珠数量
int main()
{
in(n),in(c);//输入
for(rg int i = 1;i <= c; ++i)
{//枚举
int x = read();//输入每种颜色的数量
for(rg int j = 1;j <= x; ++j)//保存每个珍珠的颜色
s[++k] = i;//每次k加1,s[k] = i即可
}
n >>= 1;//N /= 2
for(rg int i = 1;i <= n; ++i)//截半枚举
out(s[i]),cout<<" ",outn(s[i + n]);//截半输出
return 0;
}