1. 程式人生 > 實用技巧 >Day2 數對計算

Day2 數對計算

題面如下

題目描述

給出 n 個二元組 (a_i,b_i) 。對於兩個數對 (a_i,t),(a_j,t) ,可以將它們合併為 (a_i+a_j,t) 。現在,你可以按照上述規則選擇數對進行合併,求最大的 \sum_{i=1}^ma_i^2 ,其中 m

是你合併後的數對個數。

輸入格式

第一行一個整數 n ,表示數對個數。
接下來 n 行,第 i 行有兩個整數 (a_i,b_i) ,表示第 i 個數對。

輸出格式

一行一個整數,表示答案。

樣例

樣例輸入

3
5 1
3 1
3 2

樣例輸出

73

資料範圍與提示

對於 10\% 的資料, n=1
對於 30\% 的資料, n\le 1000
另有 20\% 的資料, a_i=1
另有 30\% 的資料, b_i\le 1000
對於 100\% 的資料,

1\le n\le 10^5,1\le a_i\le 10^4,1\le b_i\le 10^9

題解部分

這道題的思路真的非常簡單
對於二元組中任意兩個數對\((a_i,t)\),$(a_j,t),為了讓 \(\sum^{m}_{i=1}{a_i^2}\) 最大,我們必須合併所有可以合併的數對。證明如下:
若數對一為\((a,t)\),數對二為\((b,t)\)。若a,b未合併,二者和為:\(a^2+b^2\)。若二者合併,則值為:\((a+b)^2\)
因為:
\(a>0,b>0.(a+b)^2=a^2+2ab+b^2\)
所以:
\((a+b)^2>a^2+b^2\)
由此可證明我們的思路正確。
接下來就沒什麼難的了,程式碼實現如下:

#include<bits/stdc++.h>
#define ll long long
const int N=1e6+10;
using namespace std;
struct dui
{
	ll a;
	ll z;
}arr[N];
dui hou[N];
ll n;
ll ans;
ll cnt;
bool cmp(dui mm,dui nn)
{
	return mm.z<nn.z;
}
int main()
{
	freopen("expedition.in","r",stdin);
	freopen("expedition.out","w",stdout);
	cin>>n;
	for(ll i=1;i<= n;i++)
	{
		cin>>arr[i].a>>arr[i].z;
	}
	sort(arr+1,arr+n+1,cmp);
	for(ll i=1;i<=n;i++)
	{
		if(arr[i].z==arr[i-1].z)
		{
			hou[cnt].a+=arr[i].a;
		}
		if(arr[i].z!=arr[i-1].z)
		{
			cnt++;
			hou[cnt].a+=arr[i].a;
		}
	}
	for(ll i=1;i<=cnt;i++)
	{
		ans+=hou[i].a*hou[i].a;
	}
	cout<<ans<<endl;
	return 0;
}