uoj280 【UTR #2】題目難度提升

題面

http://uoj.ac/problem/280

題解

好久沒有更博客了啊。。
這題,官方題解似乎炸了,403了,網上也沒有找不到
那就來填一下坑吧
當然,可能寫得不是很嚴謹。。那大家就感受一下?

首先,通過玩樣例二,我們可以發現,如果說,我們存在一箇中間的數,他出現了兩次或以上,那麼我們顯然就讓他一直作爲中位數是最優的,然後填數一定是一小一大,一小一大這麼填。你會發現,在這種情況下,這個填數方案是最優的。

因爲要字典序最大,因此,我們一定希望前面的人最大
先考慮一下沒有相同的數怎麼做
容易發現這麼一個結論,就是如果你當前的還沒有填的最小值比中位數要小
那麼你一定GG了
因爲你無論在什麼時候,填入這個最小值,他都會使得中位數變小
那麼就不難得到一個做法,就是我們在每一位填之前,尋找一個我們能填的最大的數,且滿足填了以後,最小的數還是不比中位數小的是什麼,這個用set就能解決了
至於怎麼維護中位數,我們可以維護兩個堆

然後,我們再來考慮一下有相同的數怎麼做?
如果相同的數,出現在中間數以後,也就是座標在(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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章