题面
题解
好久没有更博客了啊。。
这题,官方题解似乎炸了,403了,网上也没有找到
那就来填一下坑吧
当然,可能写得不是很严谨。。那大家就感受一下?
首先,通过玩样例二,我们可以发现,如果说,我们存在一个中间的数,他出现了两次或以上,那么我们显然就让他一直作为中位数是最优的,然后填数一定是一小一大,一小一大这么填。你会发现,在这种情况下,这个填数方案是最优的。
因为要字典序最大,因此,我们一定希望前面的人最大
先考虑一下没有相同的数怎么做
容易发现这么一个结论,就是如果你当前的还没有填的最小值比中位数要小
那么你一定GG了
因为你无论在什么时候,填入这个最小值,他都会使得中位数变小
那么就不难得到一个做法,就是我们在每一位填之前,寻找一个我们能填的最大的数,且满足填了以后,最小的数还是不比中位数小的是什么,这个用set就能解决了
至于怎么维护中位数,我们可以维护两个堆
然后,我们再来考虑一下有相同的数怎么做?
如果相同的数,出现在中间数以后,也就是坐标在
(
n
+
1
)
/
2
(n+1)/2
(n+1)/2以后,那么他肯定是没有用的。因为最后的中位数一定比这些数小,因此,我们不可能存在一个时刻,使得这些数成为中位数,那么也就是他们是不是一样的没有任何影响,只是拿来凑数的,可以直接把他们看做不同的,并不会影响答案。
那么,我们再考虑,如果这些数出现在中间数之前,那么显然地,我们可以让前半段的中位数直接变成他。具体来说,就是我们找一个在最大的一个有重复数字的,然后和之前第一步那个一样。先填两个,然后一小一大,一小一大地填。
然后剩下的数,就是没有重复的了
直接按照没有相同的数来做就OK了
接着这题就做完了,代码也挺好写的
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
using namespace std;
const int N=100005;
int A[N];
int n;
bool ok[N];//这个点用了没
priority_queue<int> a,b;
void Push (int x)
{
if (a.empty()||x<=a.top()) a.push(x);
else b.push(-x);
if (a.size()<b.size()) {int x=b.top();b.pop();a.push(-x);}
if (a.size()>b.size()+1) {int x=a.top();a.pop();b.push(-x);}
}
multiset<int> s;
multiset<int>::iterator it;
int main()
{
scanf("%d",&n);
for (int u=1;u<=n;u++) scanf("%d",&A[u]);
sort(A+1,A+1+n);int mid=(n+1)>>1;
if (A[mid]==A[mid+1])
{
while (A[mid]==A[mid+1]) mid++;
printf("%d ",A[mid]);
int p=n,q=mid-1;
while (p>mid||q>0)
{
if (q>0) printf("%d ",A[q--]);
if (p>mid) printf("%d ",A[p--]);
}
return 0;
}
memset(ok,false,sizeof(ok));
while (mid>1&&A[mid-1]!=A[mid]) mid--;
ok[mid]=true;
printf("%d ",A[mid]);
int p=n,q=mid-1;
while (p>mid&&q>0)
{
ok[q]=true;printf("%d ",A[q--]);
ok[p]=true;printf("%d ",A[p--]);
}
for (int u=1;u<=n;u++)
{
if (ok[u]) Push(A[u]);
else s.insert(A[u]);
}
while (!s.empty())
{
int x=*s.begin();
int ans;
if (a.size()==b.size())//加入这个数以后是变成单个数的
{
if (x>=(-b.top())) ans=*(--s.end());
else ans=x;
}
else//变成平均数的
{
if (!b.empty()&&(x*2>=a.top()-b.top())) ans=*(--s.end());
else
{
ans=*(--s.upper_bound(x*2-a.top()));
}
}
printf("%d ",ans);
Push(ans);s.erase(s.find(ans));
}
return 0;
}