题解 题目难度提升
Description
Solution
如果没有相同的数 , 那么每次只要加入比中位数小的数就会是中位数变小 , 加入比中位数大的数就会使中位数变大 .
所以一个前缀合法的条件是当前数列的中位数小于等于未放入的所有数 .
那么直接贪心地放数即可 , 具体策略可以看一下题解 (有一些修改) .
最开始先放最小的数 , 每一阶段放两个数进去 . 阶段开始时因为有奇数个数 , 所以中位数一定落在某个数上 .
假设开始时中位数是 \(m\), 大于 \(m\) 的第一个还没有放的数是 \(K\), 如果 \((m,K)\) 中已经有数放了 , 那么这个数不管放什么都可以 , 直接放最大的数就可以了 . 否则新放入数后的现在的中位数后面的数 \(a\) 一定要满足 \(a+m\leq 2K\), 即 \(a\leq 2K−m\), 令 \(R=2K−m\). 如果 \((m,R]\) 中已经有数了 , 直接放最大的数就可以了 , 否则找到 \((m,R]\) 中最大的数放进去即可 .
假设此时中位数是 \(M\), 大于等于 \(M\) 的第一个还没有放的数是 \(L\), 如果 \((m,L)\) 中已经有数放了 , 那么直接放最大的数 , 否则就只能放 \(L\) 了 .
对于存在相同的数的情况 , 可以将第一个小于等于中位数的出现过至少两次的数放在最前面 记为 \(x\), 因为若放比它更大的数 , 那么限制就和没有相同数一样 , 而这时还没有放入最小数 , 所以必定无解 .
然后就可以贪心地先放一个最大数 , 再放一个小于等于 \(x\) 的最大数 , 直到小于等于 \(x\) 的数都被用完 , 然后问题就和没有相同数一样了 .
时间复杂度 \(O(n\log n)\)
Code
#include<iostream>
#include<cstdio>
#include<set>
#include<queue>
#include<vector>
using namespace std;
int read()
{
int ret=0;char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+(c^48),c=getchar();
return ret;
}
int n;
multiset<int>chosen,las;
priority_queue<int>q1;
priority_queue<int,vector<int>,greater<int>>q2;
int mid()
{
if((q1.size()+q2.size())&1)return q1.top()*2;
else return q1.top()+q2.top();
}
void insert(int x)
{
if(!q1.size()||x<=q1.top())q1.push(x);
else q2.push(x);
while((int)q1.size()-(int)q2.size()>1){q2.push(q1.top());q1.pop();}
while(q2.size()>q1.size()){q1.push(q2.top());q2.pop();}
chosen.insert(x);las.erase(las.find(x));
printf("%d ",x);
}
int judge()
{
for(int i:las)
{
if(!q1.size()||i<=q1.top())q1.push(i);
else q2.push(i);
while((int)q1.size()-(int)q2.size()>1){q2.push(q1.top());q1.pop();}
while(q2.size()>q1.size()){q1.push(q2.top());q2.pop();}
}
int ret=0,m=mid();
for(int i:las)
{
if(i*2>m)break;
if(i==ret)continue;
if(las.count(i)>=2)ret=i;
}
while(!q1.empty())q1.pop();while(!q2.empty())q2.pop();
return ret;
}
namespace sub1
{
void solve(int x)
{
insert(x);insert(x);
auto it=las.upper_bound(x);
while(!las.empty()&&*las.begin()<=x)
{
insert(*(--las.end()));
if(las.empty())break;
it=--las.upper_bound(x);
insert(*it);
}
if(las.size()&&!(chosen.size()&1))insert(*(--las.end()));
}
}
namespace sub2
{
void solve()
{
while(las.size())
{
int m=mid()/2;
auto k=las.lower_bound(m);
int r=*k*2-m;
auto it=chosen.upper_bound(m);
if(it!=chosen.end()&&*it<=r)insert(*(--las.end()));
else
{
it=--las.upper_bound(r);
insert(*it);
}
m=(mid()+1)/2;
if(!las.size())break;
auto l=las.lower_bound(m);
it=chosen.lower_bound(m);
if(it!=chosen.end()&&*it<=*l)insert(*(--las.end()));
else insert(*l);
}
}
}
int main()
{
n=read();
for(int i=1;i<=n;i++)las.insert(read());
int k;
if(k=judge())sub1::solve(k);
else insert(*las.begin());
sub2::solve();
return 0;
}