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;
    }


  • 相关阅读:
    ul内的li横向排列左右滑动
    git使用中常见报错解决方法
    vue 中子组件用watch方法监听父组件传来的参数,用handler方法绑定,当父组件参数不改变时,handler方法不执行
    [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders.
    vue 动态更改classname
    react怎么添加运用自定义组件
    app项目中遇到TCP分包,H5端对分包进行拼包
    Error: Invalid CSS after "xxx": expected 1 selector or at-rule, was "{}"
    'touch' 不是内部或外部命令,也不是可运行的程序或批处理文件。
    微信小程序调用快递物流查询API的实现方法
  • 原文地址:https://www.cnblogs.com/wiklvrain/p/8179317.html
Copyright © 2011-2022 走看看