zoukankan      html  css  js  c++  java
  • 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;
    }


  • 相关阅读:
    冒泡排序及优化
    Map的三种遍历
    抽象类以及接口的异同
    安卓仿制新浪微博(一)之OAuth2授权接口
    安卓handler.post问题
    Git——版本控制器概述
    Linux概述及简单命令
    JBoss7配置-支持IPv4和IPv6双栈环境
    作用域public,private,protected,以及不写时的区别
    UML类图画法及类之间几种关系
  • 原文地址:https://www.cnblogs.com/wiklvrain/p/8179317.html
Copyright © 2011-2022 走看看