题目链接: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 ; }