- 分享
- @ 2025-10-13 20:15:04
这个题目有一点坑
我当时一眼以为是DP(本人DP不太擅长)
正解
我们可以按照b从从小到大排序
然后我们就先选前\(k\)个,因为b已经排好序了,所以\(b_k\)就是答案,然后记一个sum表示当前选的物品总和是多少。还有一个ans,每轮实时更新答案并记录
然后对于\(i=k,k+1,k+2,...,n\),我们可以去看当前的\(a_i\)有没有比前\(k\)个里面的最大值来的小。如果是的话,那么sum就更新,然后在加上\(b_i\),最后ans取min
那么这个时候,我们的时间复杂度是(T太小了,就不考虑了)O(k²n),不能通过。
这个时候,我们想到了———
堆
那么我们就可以O(1)的求出最小值了,但是插入操作是log的,但是还是可以通过。
最终,时间复杂度是O(nklogk)
代码如下
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,k;
struct info{
ll a,b;
}p[1000001];
bool cmp(info A,info B){
return A.b<B.b;
}
void solve(){
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>p[i].a;
for(int i=1;i<=n;i++) cin>>p[i].b;
sort(p+1,p+n+1,cmp);
priority_queue<ll> pq;
ll ans=0,sum=0;
for(int i=1;i<=k;i++){
pq.push(p[i].a);
sum+=p[i].a;
}
ans=sum+p[k].b;
for(int i=k+1;i<=n;i++){
if(!pq.empty()&&p[i].a<pq.top()){
sum-=pq.top();
pq.pop();
pq.push(p[i].a);
sum+=p[i].a;
}
ans=min(ans,sum+p[i].b);
}
cout<<ans<<endl;
}
int main(){
cin.tie(0)->sync_with_stdio(0);
freopen("buy.in","r",stdin);
freopen("buy.out","w",stdout);
int t;
cin>>t;
while(t--) solve();
}
注意!
1.注意爆int
2.pq默认的是小根堆,然后最大值在顶端
3.对应的,大根堆是最小值在顶端,如下写法
priority_queue<T,vector<T>,greater<T> >
在某些语法中,最后两个尖括号要分开,不然会判断成流,然后报错!
0 条评论
目前还没有评论...