• Educational Codeforces Round 6 D. Professor GukiZ and Two Arrays 二分


    D. Professor GukiZ and Two Arrays

    题目连接:

    http://www.codeforces.com/contest/620/problem/D

    Description

    Professor GukiZ has two arrays of integers, a and b. Professor wants to make the sum of the elements in the array a sa as close as possible to the sum of the elements in the array b sb. So he wants to minimize the value v = |sa - sb|.

    In one operation professor can swap some element from the array a and some element from the array b. For example if the array a is [5, 1, 3, 2, 4] and the array b is [3, 3, 2] professor can swap the element 5 from the array a and the element 2 from the array b and get the new array a [2, 1, 3, 2, 4] and the new array b [3, 3, 5].

    Professor doesn't want to make more than two swaps. Find the minimal value v and some sequence of no more than two swaps that will lead to the such value v. Professor makes swaps one by one, each new swap he makes with the new arrays a and b.

    Input

    The first line contains integer n (1 ≤ n ≤ 2000) — the number of elements in the array a.

    The second line contains n integers ai ( - 109 ≤ ai ≤ 109) — the elements of the array a.

    The third line contains integer m (1 ≤ m ≤ 2000) — the number of elements in the array b.

    The fourth line contains m integers bj ( - 109 ≤ bj ≤ 109) — the elements of the array b.

    Output

    In the first line print the minimal value v = |sa - sb| that can be got with no more than two swaps.

    The second line should contain the number of swaps k (0 ≤ k ≤ 2).

    Each of the next k lines should contain two integers xp, yp (1 ≤ xp ≤ n, 1 ≤ yp ≤ m) — the index of the element in the array a and the index of the element in the array b in the p-th swap.

    If there are several optimal solutions print any of them. Print the swaps in order the professor did them.

    Sample Input

    5
    5 4 3 2 1
    4
    1 1 1 1

    Sample Output

    1
    2
    1 1
    4 2

    Hint

    题意

    给你两个数组,a数组和b数组

    你可以用a数组中的一个数,交换到b数组去

    然后使得abs(suma-sumb)最小

    你最多交换两次

    让你输出方案

    题解:

    交换0次和交换一次,显然可以直接暴力出来

    现在考虑交换两次的情况,交换两次之后,答案为s-2*a[i]-2*a[j]+2*b[i]-2*b[j](s为原来未交换的时候,两个数组的差值

    我们把所有的(a[i],a[j])都存起来,为了使两数组之差最小,显然2*(b[i]+b[j])应该找到大于等于(2*(a[i]+a[j])-s)的第一个数

    然后这个东西直接二分就好了

    然后这道题就结束了。。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2050;
    int a[maxn];
    int b[maxn];
    pair<int,int> ans1;
    pair<int,int> ans21,ans22;
    pair<long long ,pair<int,int> >two[maxn*maxn+5];
    int tot = 0;
    int main()
    {
        long long s = 0;
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),s+=a[i];
        int m;scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d",&b[i]),s-=b[i];
        long long s2 = 1e18;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                long long cur = abs(s + 2*b[j] - 2*a[i]);
                if(cur<s2)
                {
                    s2 = cur;
                    ans1=make_pair(i,j);
                }
            }
        }
        for(int i=1;i<=m;i++)
            for(int j=i+1;j<=m;j++)
                two[++tot]=make_pair(2ll*b[i]+2ll*b[j],make_pair(i,j));
        sort(two+1,two+1+tot);
        long long s3 = 1e18;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                long long tmp = 2ll*a[i]+2ll*a[j]-s;
                int p = lower_bound(two+1,two+1+tot,make_pair(tmp,make_pair(0,0)))-two;
                for(int t=max(1,p-2);t<=min(tot,p+2);t++)
                {
                    long long cur = abs(s+two[t].first-2ll*a[i]-2ll*a[j]);
                    if(cur<s3)
                    {
                        s3 = cur;
                        ans21 = make_pair(i,two[t].second.first);
                        ans22 = make_pair(j,two[t].second.second);
                    }
                }
            }
        }
        long long ans = min(min(abs(s),abs(s2)),abs(s3));
        printf("%lld
    ",ans);
        if(ans==s)
            printf("0
    ");
        else if(abs(s2)==ans)
        {
            printf("1
    ");
            printf("%d %d
    ",ans1.first,ans1.second);
        }
        else
        {
            printf("2
    ");
            printf("%d %d
    %d %d
    ",ans21.first,ans21.second,ans22.first,ans22.second);
        }
    }
  • 相关阅读:
    ubuntu20.04上实现百度Apollo6.0系统的部署
    matplotlib包图例出现中文乱码问题
    微软官方Silverlight 音频播放器 Jonas修整版(silerlight 2.0版)
    SpringCloud总结1
    Java中文长度计算
    注册退出函数:atexit
    函数参数的一种特殊用法
    new与malloc等的区别
    两种多态
    第一章 1.1.2 因特网提供服务的方式
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5217014.html
Copyright © 2020-2023  润新知