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\n",ans);
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/carcar/p/10468421.html