1. 程式人生 > >Codeforces-620d Professor GukiZ and Two Arrays

Codeforces-620d Professor GukiZ and Two Arrays

題目大意:

給你兩個陣列,一個長度為n,一個長度為m,第一個陣列各個元素的和為suma,第二個陣列各個元素的和為sumb,現在想要通過交換兩個陣列元素的方式使Abs(suma - sumb)最小,但是交換的次數不能超過兩次。讓你輸出Abs(suma - sumb)的最小值,並輸出這個值發生的時候的交換次數和交換元素在兩個陣列中的下標。

解題思路:

首先看到這題我們需要明確一下資料大小,n和m的大小都是隻有2000,而交換的次數不會超過兩次,那麼我們就可以簡單暴力的寫了。

列舉交換的次數:

當不交換的時候,就是一次遍歷陣列然後得出結果的情況。複雜度O(n+m)

當交換一次的時候,列舉兩個陣列會交換的所有情況即可。複雜度O(nm)

當交換兩次的時候:

首先,假設第一個陣列交換的元素為下標a和b的元素,第二個陣列交換的元素為下標c和d的元素。

然後,我們可以簡單的得到一個算式Abs(suma' - sumb')=Abs(suma - sumb - 2 * (array1[a] + array1[a]) - 2 * (array2[c] + array2[d]))

我們的目的是計算最小的Abs(suma' - sumb'),而abs不可能為負數

所以,當我們已知suma - sumb - 2 * (array1[a] + array1[b])的情況下,可以找離-(suma - sumb - 2 * (array1[a] + array1[b])

)最近的一個元素。

怎麼找呢,前面說了,在已知suma - sumb - 2 * (array1[a] + array1[b])的情況下,也就是說我們已知array1[a]+array1[b],所以只需要先在兩個陣列中,枚舉出所有的兩個元素相加的情況,就能夠利用二分查詢,得到我們想要的結果了。

複雜度是O(n*(n-1) / 2 + m*(m-1) / 2 + n * (n - 1) / 2 * log(m * (m-1) / 2))。也就是O(n^2)的複雜度。

程式碼:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2e3 + 2;

int a[maxn], b[maxn];
vector<pair<int, int> > vec;
vector<pair<long long, pair<int, int> > > aa, bb;

template<typename T> T Abs(T x) { return (x >= 0 ? x : -x); }
template<typename T> T Max(T x, T y) { return (x >= y ? x : y); }
template<typename T> T Min(T x, T y) { return (x <= y ? x : y); }

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	int n, m; long long ans = 0;
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> a[i];
		ans += a[i];
	}
	cin >> m;
	for (int i = 0; i < m; ++i) {
		cin >> b[i];
		ans -= b[i];
	}
	long long sum = ans; ans = Abs(ans);
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			if (ans > Abs(sum - 2 * a[i] + 2 * b[j])) {
				ans = Abs(sum - 2 * a[i] + 2 * b[j]);
				vec.clear();
				vec.push_back(make_pair(i + 1, j + 1));
			}
		}
	}
	
	if (!(n <= 1 || m <= 1)) {
		aa.clear();
		for (int i = 0; i < n; ++i) 
			for (int j = i + 1; j < n; ++j) 
				aa.push_back(make_pair(a[i] + a[j], make_pair(i + 1, j + 1)));
		for (int i = 0; i < m; ++i) 
			for (int j = i + 1; j < m; ++j)
				bb.push_back(make_pair(b[i] + b[j], make_pair(i + 1, j + 1)));
		
		sort(aa.begin(), aa.end());
		sort(bb.begin(), bb.end());
		
		for (decltype(aa.size()) i = 0; i < aa.size(); ++i) {
			long long tmp = (2 * aa[i].first - sum) / 2;
			int idx = lower_bound(bb.begin(), bb.end(), make_pair(tmp, make_pair(0, 0))) - bb.begin();
			if (idx < bb.size() && ans > Abs(sum - 2 * aa[i].first + 2 * bb[idx].first)) {
				ans = Abs(sum - 2 * aa[i].first + 2 * bb[idx].first);
				vec.clear();
				vec.push_back(make_pair(aa[i].second.first, bb[idx].second.first));
				vec.push_back(make_pair(aa[i].second.second, bb[idx].second.second));
			}
			if (idx > 0 && ans > Abs(sum - 2 * aa[i].first + 2 * bb[idx - 1].first)) {
				ans = Abs(sum - 2 * aa[i].first + 2 * bb[idx - 1].first);
				vec.clear();
				vec.push_back(make_pair(aa[i].second.first, bb[idx - 1].second.first));
				vec.push_back(make_pair(aa[i].second.second, bb[idx - 1].second.second));
			}
		}
	}
	
	cout << ans << endl;
	cout << vec.size() << endl;
	for (auto& a: vec) 
		cout << a.first << " " << a.second << endl;
	return 0;
}