[ABC376E] Max × Sum
[ABC376E] Max × Sum
题意
给出 \(A_1,A_2,\cdots,A_N\),\(B_1,B_2,\cdots,B_N\)。
令 \(S\) 为 \(\lbrace1, 2, \dots, N\rbrace\) 的一个大小为 \(K\) 的子集,问该表达式的最小值:
\[\displaystyle \left(\max_{i \in S} A_i\right) \times \left(\sum_{i \in S} B_i\right)
\]
思路
可以发现 \(\max_{i\in S} A_i\) 最多只有 \(N\) 种取值,于是可以将 \(A,B\) 按照 \(A_i\) 升序排序,设 \(x\) 为 \(S\) 中的最大数字,则问题可以转换成求以下表达式的最小值:
\[A_x\times \left(\sum_{i \in S} B_i\right)
\]
这时再枚举 \(x\),则只需要最小化 \(\sum_{i \in S} B_i\)。因为选了 \(A_x\),所以 \(B_x\) 一定被选,剩下的 \(B_i\) 则取前 \((x-1)\) 项的前 \((K-1)\) 小值,该过程可以使用 multiset 维护。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,n,k,ans;
struct node{
int x,y;
}a[2000005];
bool cmp(node x,node y){
return x.x<y.x;
}
multiset<int> bg;
signed main(){
ios::sync_with_stdio(false);
cin.tie(),cout.tie();
cin>>T;
while(T--){
bg.clear(),ans=LONG_LONG_MAX;
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i].x;
for(int i=1;i<=n;i++)
cin>>a[i].y;
sort(a+1,a+1+n,cmp);
int nw=0;
for(int i=1;i<k;i++)
bg.insert(a[i].y),nw+=a[i].y;
for(int i=k;i<=n;i++){
ans=min(ans,(nw+a[i].y)*a[i].x);
if(k!=1){//k=1时multiset为空,于是喜提RE
if(a[i].y<*--bg.end()){//比前k-1小的最大值还小
nw-=*--bg.end();
bg.erase(--bg.end());
nw+=a[i].y;
bg.insert(a[i].y);
}
}
}
cout<<ans<<endl;
}
return 0;
}

浙公网安备 33010602011771号