题意:给出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; }