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

· · 题解

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

题目描述

按照任意顺序逐个将数字添加到 $m$ 中,使得在每一步添加完当前数字后,集合 $m$ 元素的中位数始终保持为整数。 ## 初始思路 我们假定一个情况,当数组处于一个稳定状态时,当且仅当在此之后我们以一种特定顺序添加 $a_i$ ,可以保证 $m$ 的中位数是整数。 是否可能有这个稳定状态存在呢?这时数组的奇偶性会给予我们很强的提示。 为什么是奇偶性?因为我们如果处于稳定状态,那么上述所说的特殊顺序更可能是以有序数列的中点为中心,左一个右一个地添加,这显然是成对出现的,也就是存在奇偶性区别。 至于为什么左右轮流添加可行,~~这就好比你在一层一层剥橘子一样,~~ 这是在于我们只要先把两个中间的数加进来,之后成对加数不会改变 $m$ 的中位数。证毕。 ## 具体着手 假设 $n$ 为偶数,那么根据刚刚的思路,我们将以左一个右一个的顺序添加 $a_i$ 。在进入稳定状态之前,我们一定要保证 $a_i$ 的中位数为整数。 这是显然的,当你把所有的 $a_i$ 加进去了,最终 $m$ 的中位数和原来 $a$ 数组的中位数就是一致的。后者不为整数,前者一定不为整数,条件就无法实现了。 而当 $a_i$ 的中位数为整数时,我们一定可以按照上述特殊顺序执行操作。请读者自证。 ::::info[提示] 考虑加数的时候当前容量为奇数时发生什么?偶数时发生什么? :::: 假设 $n$ 为奇数,那我们考虑将未知问题转化为已知问题。接下来注意到一个重要推论: ``` 如果我们移除一个数后,其余数满足偶数情况,那么奇数情况一定成立。 ``` 为什么?证明是显然的。 如果你移除一个数后,剩余的满足偶数条件,那你不妨先把除了这个数外的其他 $a_i$ 按照偶数情况加到 $m$ 里,最后再把这个数加进去。加完之后 $m$ 显然有奇数个整数,根据题意, $m$ 的中位数一定是整数,那么推论证毕。 ## 代码实现 ::::info[代码] ```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; } ``` ::::