Codeforecs 439D Devu and his Brother 三分

来源:互联网 发布:ubuntu安装32位运行库 编辑:程序博客网 时间:2024/05/16 19:36

点击打开链接

题意:给出两个序列a,b 操作:使某个元素增加1或者减少1 

问使序列a中最小值>=序列b中最大值的最少操作次数? n,m<=1e5,a[i],b[i]<=1e9



f(x) x增加 前半部分增加 后半部分减小. 最极大和极小时,f(x)都较大,猜f(x)为凸函数.
Proof: f(x)求导  f'(x)=cnt-num  (cnt为a中小于x的个数,num为b中大于x的个数) x增大,f'(x)增大

f'(x)单调递增 f''(x)>=0 推出 f(x)为凸函数 三分求极值即可


#include <bits/stdc++.h>using namespace std;typedef long long ll;const double eps=1e-10;const int inf=0x3f3f3f3f;const int N=2e5+20;ll n,m,a[N],b[N];ll f(ll x){ll res=0;for(int i=1;i<=n;i++)res+=max(0ll,x-a[i]);for(int i=1;i<=m;i++)res+=max(0ll,b[i]-x);return res;}void Ternary_Search(){ll l=1,r=2e9,ans=2e16;while(l<r){ll m1=(l+r)/2,m2=(m1+r)/2;if(f(m1)>f(m2))l=m1;elser=m2;ans=min(ans,min(f(m1),f(m2)));}cout<<ans<<endl;}int main(){while(cin>>n>>m){for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);for(int i=1;i<=m;i++)scanf("%I64d",&b[i]);Ternary_Search();}return 0;}





原创粉丝点击