题目分类:反悔贪心
思路:对于每个查询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 ;
}