题解 题目难度提升
细节颇多
当所有数都不相同时,只要加了数,中位数就一定会变化
两种情况:由两个数的平均数变为一个数或变为两个数的平均数
变两个数的情况:只要满足加数后新中位数小于等于未加的最小数就可以了
令未加的最小数为 \(k\),中位数为 \(m\),能加的数 \(r\) 要满足 \(\frac{m+r}{2}\leqslant k\)
变为一个数的情况:考虑还没加的最小的数,若已加过大小在中位数和它之间的数,这个数也就可以随便取了,否则取最小
有数相同时,可能可以让中位数在它们两个中间跳
那首先要满足这两个数都小于等于中位数
- float不但精度低,整数部分能存的范围也很小,1e9会爆
- 关于中位数的维护:考虑对顶堆
所以在加了这两个数之后可以无脑贪心
从大于等于它的和小于等于它的里各取一个最大的加进去
加完之后就和上面的情况一样了
这题还有个 \(n^4\) 暴力没想到
可以按位枚举,check一个前缀是否可行就用最劣的方案check,即把后面排序了check
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N];
namespace force{
int h[N], tem[N], ans[N];
void solve() {
for (int i=1; i<=n; ++i) h[i]=a[i];
sort(h+1, h+n+1);
do {
ll lst=0, now;
// for (int i=1; i<=n; ++i) cout<<h[i]<<' '; cout<<endl;
for (int i=1; i<=n; ++i) {
tem[i]=h[i];
stable_sort(tem+1, tem+i+1);
if (i&1) now=2ll*tem[(i+1)/2];
else now=tem[i/2]+tem[i/2+1];
// cout<<"cmp: "<<lst<<' '<<now<<endl;
if (now<lst) goto jump;
else lst=now;
}
for (int i=1; i<=n; ++i) ans[i]=h[i];
jump: ;
} while (next_permutation(h+1, h+n+1));
if (!ans[1]) {puts("QwQ"); exit(0);}
for (int i=1; i<=n; ++i) printf("%d ", ans[i]);
printf("\n");
exit(0);
}
}
namespace task{
int tem[N], tot, ans[N], top, cnt;
priority_queue<int, vector<int>, less<int>> down;
priority_queue<int, vector<int>, greater<int>> up;
multiset<int> s;
void double_R(int r) {
// if (n==100) cout<<"double_R: "<<tem[r]<<endl;
// while (r<n-1 && tem[r+2]==tem[r+1]) ++r;
up.emplace(tem[r]); ans[++top]=tem[r]; s.erase(s.find(tem[r]));
up.emplace(tem[r+1]); ans[++top]=tem[r+1]; s.erase(s.find(tem[r+1]));
while (s.size()>1 && *s.begin()<=tem[r]) {
up.emplace(*s.rbegin());
ans[++top]=*s.rbegin();
s.erase(s.find(*s.rbegin()));
auto it=s.lower_bound(tem[r]+1);
if (it==s.begin()) break;
--it;
up.emplace(*it);
ans[++top]=*it;
s.erase(s.find(*it));
}
if (s.empty()) {
for (int i=1; i<=n; ++i) printf("%d ", ans[i]); printf("\n");
exit(0);
}
}
void solve() {
for (int i=1; i<=n; ++i) tem[i]=a[i];
sort(tem+1, tem+n+1);
for (int i=1; i<=n; ++i) s.insert(tem[i]);
double m=(n&1)?(tem[(n+1)/2]):((tem[n/2]+tem[n/2+1])/2);
// if (n==100) printf("m: %.2lf\n", m);
for (int i=n-1; i; --i) if (tem[i]<=m && tem[i]==tem[i+1]) {double_R(i); break;}
cnt=n-s.size();
// cerr<<"cnt: "<<cnt<<endl;
// cout<<"s: "; for (auto it:s) cout<<it<<' '; cout<<endl;
if (!cnt) {
up.emplace(*s.begin());
ans[++top]=*s.begin();
s.erase(s.begin());
++cnt;
}
while (up.size()>cnt/2) down.emplace(up.top()), up.pop();
while (s.size()) {
// cout<<"size: "<<s.size()<<endl;
// cout<<"cnt: "<<cnt<<endl;
if (cnt&1) {
if ((!up.empty()&&up.top()<=2*(*s.begin())-down.top())) {
up.emplace(*s.rbegin());
ans[++top]=*s.rbegin();
s.erase(s.find(*s.rbegin()));
}
else {
auto it=s.upper_bound(2*(*s.begin())-down.top());
assert(it!=s.begin());
if (it==s.begin()) it=s.end();
--it;
// cout<<"it: "<<*it<<endl;
up.emplace(*it);
ans[++top]=*it;
s.erase(it);
}
}
else {
// cout<<"top: "<<up.top()<<' '<<*s.begin()<<endl;
if (up.top()>*s.begin() && *s.begin()>=down.top()) {
// cout<<"case1"<<endl;
up.emplace(*s.begin());
ans[++top]=*s.begin();
s.erase(s.begin());
}
else {
// cout<<"case2"<<endl;
up.emplace(*s.rbegin());
ans[++top]=*s.rbegin();
s.erase(s.find(*s.rbegin()));
}
}
++cnt;
while (up.size()>cnt/2) {
// cout<<up.size()<<' '<<up.empty()<<' '<<cnt/2<<endl;
down.emplace(up.top());
up.pop();
}
}
for (int i=1; i<=n; ++i) printf("%d ", ans[i]); printf("\n");
exit(0);
}
}
signed main()
{
freopen("d.in", "r", stdin);
freopen("d.out", "w", stdout);
n=read();
for (int i=1; i<=n; ++i) a[i]=read();
// force::solve();
task::solve();
return 0;
}