题目链接
问题转化:给你一个数组 a,构建一个矩阵 b,使得 bij=ai+aj,你要从矩阵中选m个数使得和最大。
显然二分一下第 n2−m+1小的数是啥,然后用总和减掉前 n2−m小的数就好了。
注意一下细节:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5+10;
#define fi first
#define se second
#define pb push_back
int n;
LL a[N],m;
LL ans,sum[N];
int main() {
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
LL l=a[1]+a[1],r=a[n]+a[n],res=l;
LL ne=m;
m=1ll*n*n-m+1;
while(l<=r){
LL mid=l+r>>1;
LL tot=0;
for(int i=1;i<=n;i++){
if(a[i]>=mid)break;
LL x=mid-a[i];
tot+=upper_bound(a+1,a+1+n,x)-a-1;
}
if(tot>=m)r=mid-1,res=mid;//二分找到第k-th小值
else l=mid+1;
}
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
for(int i=1;i<=n;i++)ans+=a[i]*n+sum[n];
LL pa=0;
for(int i=1;i<=n;i++){
int l=1,r=n,d=0;
while(l<=r){
int mid=l+r>>1;
if(a[mid]<res-a[i])d=mid,l=mid+1;
else r=mid-1;
}
ans-=d*a[i]+sum[d];
pa+=d;
}
cout<<ans-(m-1-pa)*res<<'\n';//还有没减完的再减一下
return 0;
}