[Codeforces 841C]Leha and Function

题目大意:定义函数F(n,k)为[1,2,3,..n]中k个元素的子集中最小元素的数学期望。现在给你两个长度相等的数列A,B(A中元素严格大于B中元素),现在要你重新排列A,使得$sumlimits _{i=1}^m F(A'[i],B[i])$最大。求排完后的A'。

解题思路:首先找规律,得出$F(n,k)=frac{n+1}{k+1}$。

然后进行贪心,将B[i]中小的元素对应A[i]中大的元素。为什么这样做是对的?随便举四个正整数$x,y,a,b(x<y<a<b)$,比较$frac{a+1}{x+1}+frac{b+1}{y+1}$和$frac{b+1}{x+1}+frac{a+1}{y+1}$的大小即可得出。

如果没找出规律,则可以观察样例,发现B[i]越小A[i]越大,则也能得出正解。

于是我们把B[i]升序排序,A[i]降序排序,然后把A'[i]按照B[i]原来的位置排列即可。

观察样例发现字典序要最小,那么我们将B[i]的位置作为第二关键字,越大放在越前面,即可保证字典序最小。

时间复杂度$O(nlog_2 n)$。

C++ Code:

#include<algorithm>
#include<cstdio>
#include<functional>
using namespace std;
struct B{
	int num,no;
	bool operator <(const B& $1)const{
		if(num!=$1.num)
		return num<$1.num;
		return no>$1.no;
	}
}b[200005];
int a[200005],n,val[200005];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	for(int i=1;i<=n;++i)scanf("%d",&b[i].num),b[i].no=i;
	stable_sort(b+1,b+n+1);
	stable_sort(a+1,a+n+1,greater<int>());
	for(int i=1;i<=n;++i)
	val[b[i].no] = a[i];
	for(int i=1;i<=n;++i) printf("%d ",val[i]);
	return 0;
} 
原文地址:https://www.cnblogs.com/Mrsrz/p/7691427.html