1. 程式人生 > >codeforces#439 D. Devu and his Brother (二分)

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

最大 sca sha main cout 修改 ace \n 最小值

題意:給出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;
}

  

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