Description
一年一度的暑期集訓又開始了!
作爲老人的小明非常憂傷,因爲他要給所有的新人安排座位。由於安排給新人的座位上的機器可能有各種毛病(比如很卡,上不了網之類的),這些問題的出現都會讓新人的訓練熱情下降。爲了讓更多的新人能夠留下,小明自然希望大家的熱情都是高漲的。
對於每個新人,都會有一個熱情值ai,而每個座位都會有一個熱情耗損值bi,如果第i個新人坐在第j個位置,那這位同學對整個集訓隊熱情值的貢獻就是(ai - bj) ^2。現在給出所有新人的熱情值,所有位置的熱情耗損值,你能告訴小明採用最合理的位置安排方式後,能得到的最大的集訓隊熱情值是多少?
當然,每個位置只能坐一個新人,每個新人也必須坐在某個位置上
Input
第一行一個數字T表示數據組數
每組數據包括三行:
第一行爲一個整數n,表示新人的人數
第二行爲n個整數,第i個數字表示第i個同學的熱情值ai
第三行爲n個整數,第i個數字表示第i個座位的熱情耗損值爲bi
其中T<=10 , 0<=ai , bi <=100, 1<=n<=100000
Output
輸出一行只包含一個整數,表示集訓隊熱情值的最大值
Sample Input
2 3 2 5 1 0 0 1 3 2 5 1 3 2 5
Sample Output
29 26
Hint
題目大意
給出長度爲n的序列ai與bi,要求每個ai找一個bj組合,對答案貢獻(ai − bj)2,每個ai和bi都只能使用一次,問答案最大是多少
問題分析
這個問題是經典的貪心。$ ans = (a_i - b_j)^2 ,我們展開它得到 ans = a_i^2 + b_i^2$ - ***2 * ∑ai*bj。前兩部分都是固定的,所以要使得答案儘量大,我們應該使得∑ai * bj儘量小。可以猜想這麼個結論:a中最大的和b中最小的匹配,a中次大的與b中次小的匹配……這種匹配是最優的。證明使用排序不等式。
具體實現
我們將兩個數組排序,然後按照上面的策略匹配,累加答案就行了
時空複雜度
這裏時間複雜度主要來源於排序O(nlogn)
空間複雜度爲O(n)
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<cstring> using namespace std; int neww[100005]; int sit[100005]; int cmp(int a,int b) { return a>b; } int main() { int t; cin>>t; //getchar(); while(t--) { memset(neww,0,sizeof(neww)); memset(sit,0,sizeof(sit)); int num; cin>>num; for(int i = 0;i<num;i++) cin>>neww[i]; for(int i = 0;i<num;i++) cin>>sit[i]; sort(neww,neww+num); sort(sit,sit+num,cmp); long long sum = 0; for(int i = 0;i<num;i++) { double help =pow((neww[i]-sit[i]),2); sum+=help; //cout<<help<<endl; //cout<<sum<<endl; } cout<<sum<<endl; //getchar(); } } /********************************************************************** Problem: 1971 User: liyingshou Language: C++ Result: AC Time:232 ms Memory:2800 kb **********************************************************************/