• codeforces#439 D. Devu and his Brother (二分)


    题意:给出a数组和b数组,他们的长度最大1e5,元素范围是1到1e9,问你让a数组最小的数比b数组最大的数要大需要的最少改变次数是多少。每次改变可以让一个数加一或减一

    分析:枚举a数组和b数组的所有的元素x,作为他们的界限,也就是说a数组所有的数要大于等于x,b数组所有的数要小于等于x,再利用前缀和+二分,分别求出ab数组需要改变的次数,在所有的方案中取一个最小值

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1e5+10;
    ll sum1[maxn],sum2[maxn];
    int num1[maxn],num2[maxn];
    int main()
    {
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&num1[i]);
        for(int i=1;i<=m;i++)
            scanf("%d",&num2[i]);
        sort(num1+1,num1+1+n);
        sort(num2+1,num2+1+m);
        for(int i=1;i<=n;i++)
            sum1[i]=sum1[i-1]+num1[i];
        for(int i=1;i<=m;i++)
            sum2[i]=sum2[i-1]+num2[i];
        ll ans=1e18;
        for(int a=1;a<=n+m;a++)
        {
            int i;
            if(a<=n)i=num1[a];
            else i=num2[a-n];
            ll ans1,ans2;
            if(num1[1]>=i)ans1=0;
            else
            {
                int st=1,en=n;
                while(st!=en)
                {
                    int md=(st+en)/2;
                    if(num1[md+1]<=i)st=md+1;//可以修改的下标
                    else en=md;
                }
                ans1=(ll)i*st-sum1[st];
            }
            if(num2[m]<=i)ans2=0;
            else
            {
                int st=1,en=m;
                while(st!=en)
                {
                    int md=(st+en)/2;
                    if(num2[md]>=i)en=md;
                    else st=md+1;
                }
                ans2=sum2[m]-sum2[st-1]-(ll)i*(m-st+1);
            }
            //cout<<i<<" "<<ans1<<" "<<ans2<<endl;
            ans=min(ans1+ans2,ans);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    Java内置包装类
    for循环思路题
    常用函数
    函数
    冒泡排序
    数组的运用
    for循环中有意思的练习题。
    for循环
    运算中容易出现的错误
    分支的运用
  • 原文地址:https://www.cnblogs.com/carcar/p/10468421.html
Copyright © 2020-2023  润新知