题目链接:E-小A的任务_牛客小白月赛90
题目分类:反悔贪心
思路:对于每个查询k,我们需要找到最小的m(m ≥ k),使得前m个A类任务的总时间加上前m个B类任务中最小的k个任务的时间之和最小。
我们可以使用前缀和数组快速计算A类任务的总时间。对于每个查询k,使用大顶堆动态维护前m个B类任务中最小的k个任务的时间之和(反悔贪心)。时间复杂度为O(n log k)
复杂度分析:预处理前缀和数组的时间复杂度为O(n)。每个查询处理的时间复杂度为O(n log k),总复杂度为O(q * n log k)
核心代码如下
#define int long long
int a[N],b[N],pre[N];
int n,q;
void calc(int k){
int ans=1e18;
priority_queue<int>que;
int tmp=0;
Forl(i,1,n){
if((int)que.size()<k){
que.push(b[i]);
tmp+=b[i];
if((int)que.size()<k) continue;
}else{ //动态维护堆中数字,如果堆中的最大值比b[i]小,那么就把b[i]存入堆中,把原先的最大值踢出去,这样一定最优(反悔贪心思想)
if((int)que.top()>b[i]){
tmp-=(int)que.top();
que.pop();
tmp+=b[i];
que.push(b[i]);
}
}
ans=min(ans,tmp+pre[i]);
}
println(ans);
return ;
}
void InfiniteLight() {
read(n);
read(q);
Forl(i,1,n){
read(a[i]);
pre[i]=pre[i-1]+a[i];
}
Forl(i,1,n){
read(b[i]);
}
Forl(i,1,q){
int k;
read(k);
calc(k);
}
return ;
}

京公网安备 11010502036488号