专栏文章

题解:P14546 [IO 2024 #3] 整数中位数

P14546题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min3zkcb
此快照首次捕获于
2025/12/01 20:11
3 个月前
此快照最后确认于
2025/12/01 20:11
3 个月前
查看原文

P14546 [IO 2024 #3] 整数中位数

题目描述

nn 个互不相同的整数,第 ii 个数为 aia_i。 按照任意顺序逐个将数字添加到 mm 中,使得在每一步添加完当前数字后,集合 mm 元素的中位数始终保持为整数。

初始思路

我们假定一个情况,当数组处于一个稳定状态时,当且仅当在此之后我们以一种特定顺序添加 aia_i ,可以保证 mm 的中位数是整数。
是否可能有这个稳定状态存在呢?这时数组的奇偶性会给予我们很强的提示。
为什么是奇偶性?因为我们如果处于稳定状态,那么上述所说的特殊顺序更可能是以有序数列的中点为中心,左一个右一个地添加,这显然是成对出现的,也就是存在奇偶性区别。
至于为什么左右轮流添加可行,这就好比你在一层一层剥橘子一样,
这是在于我们只要先把两个中间的数加进来,之后成对加数不会改变 mm 的中位数。证毕。

具体着手

假设 nn 为偶数,那么根据刚刚的思路,我们将以左一个右一个的顺序添加 aia_i 。在进入稳定状态之前,我们一定要保证 aia_i 的中位数为整数。
这是显然的,当你把所有的 aia_i 加进去了,最终 mm 的中位数和原来 aa 数组的中位数就是一致的。后者不为整数,前者一定不为整数,条件就无法实现了。
而当 aia_i 的中位数为整数时,我们一定可以按照上述特殊顺序执行操作。请读者自证。
提示
考虑加数的时候当前容量为奇数时发生什么?偶数时发生什么?
假设 nn 为奇数,那我们考虑将未知问题转化为已知问题。接下来注意到一个重要推论:
CPP
如果我们移除一个数后,其余数满足偶数情况,那么奇数情况一定成立。
为什么?证明是显然的。
如果你移除一个数后,剩余的满足偶数条件,那你不妨先把除了这个数外的其他 aia_i 按照偶数情况加到 mm 里,最后再把这个数加进去。加完之后 mm 显然有奇数个整数,根据题意, mm 的中位数一定是整数,那么推论证毕。

代码实现

代码CPP
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N],ret,b[N];
void p_work()
{
	for(int i=(n>>1);i;i--) printf("%d %d ",a[i],a[n-i+1]);
	return;
}
bool check()
{
	for(int i=1;i<=n;i++) 
	{
		int l=i-1,r=n-i;
		int posl,posr,mid=(n-1)>>1;
		if(l==r) posl=i-1,posr=i+1;
		else if(mid+1<=l) posl=mid,posr=mid+1;
		else posl=mid+1,posr=mid+2;
//		printf("i=%d posl=%d,posr=%d\n",i,posl,posr);
		if((a[posl]+a[posr])%2==0)
		{
			ret=a[i];
			for(int j=1;j<=i-1;j++)  b[j]=a[j];
			for(int j=i+1;j<=n;j++) b[j-1]=a[j];
			return true;
		}
	}
	return false;
}
void q_work()
{
	for(int i=((n-1)>>1);i;i--) printf("%d %d ",b[i],b[n-i]);
	printf("%d",ret);
	return;
}
signed main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	if(n%2==0)  
	{
//		printf("pos:%d %d\n",n>>1,(n>>1)+1);
		if((a[n>>1]+a[(n>>1)+1])%2==0) p_work();
		else puts("-1");
	}
	else
	{
		if(!check()) puts("-1");
		else q_work();
	}
	return 0;
} 

评论

0 条评论,欢迎与作者交流。

正在加载评论...