Codeforces Round #251 Div2D 439D Devu and his Brother 二分查找STL
非常水的题目……我交了四次。
注意到一个性质,就是改动到的那个数字一定在数组a或者数组b里面。维护一下第一个数组的前缀和和第二个数组的后缀和。
这样我们枚举每个元素。在还有一个数组中二分查找就可以。
//CF439D #include<iostream> #include<cstdio> #include<algorithm> #include<string> #include<cstring> #include<vector> #include<queue> #include<climits> using namespace std; typedef long long LL; int n,m; LL a[100010],b[100010],sa[100010],sb[100010],ans=LONG_LONG_MAX; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%I64d",&a[i]); for(int i=1;i<=m;i++) scanf("%I64d",&b[i]); sort(a+1,a+n+1);sort(b+1,b+m+1); for(int i=1;i<=n;i++) sa[i]=sa[i-1]+a[i]; for(int i=m;i>=1;i--) sb[i]=sb[i+1]+b[i]; for(int i=1;i<=n;i++) { int sub=upper_bound(b+1,b+m+1,a[i])-b; LL p=(i-1)*a[i]-sa[i-1]+sb[sub]-(m+1-sub)*a[i]; ans=min(ans,p); } for(int j=1;j<=m;j++) { int sub=upper_bound(a+1,a+n+1,b[j])-a; LL p=(sub-1)*b[j]-sa[sub-1]-(m-j)*b[j]+sb[j+1]; ans=min(ans,p); } printf("%I64d\n",ans); return 0; }
二分查找不用手写:
查找在a数组中,1~n下标内,大于tar的最小下标。
(数组a有序)
upper_bound(a+1,a+n+1,tar);
查找在a数组中。1~n下标内,大于或等于tar的最小下标。
(数组a有序)
lower_bound(a+1,a+n+1,tar);