1. 程式人生 > >[Codeforces 841C]Leha and Function

[Codeforces 841C]Leha and Function

its 得出 數列 原來 struct != using %d span

題目大意:定義函數F(n,k)為[1,2,3,..n]中k個元素的子集中最小元素的數學期望。現在給你兩個長度相等的數列A,B(A中元素嚴格大於B中元素),現在要你重新排列A,使得$\sum\limits _{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(n\log_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;
} 

[Codeforces 841C]Leha and Function