题解 题目难度提升

传送门

细节颇多

当所有数都不相同时,只要加了数,中位数就一定会变化
两种情况:由两个数的平均数变为一个数或变为两个数的平均数
变两个数的情况:只要满足加数后新中位数小于等于未加的最小数就可以了
令未加的最小数为 \(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;
}
posted @ 2021-09-27 06:22  Administrator-09  阅读(3)  评论(0编辑  收藏  举报