洛谷 P2949 [USACO09OPEN] Work Scheduling G
思路:反悔贪心
首先,我们看每一个工作,如果目前这个工作可以做,就做,否则看这个工作是否比目前已经做了的工作中最便宜的更赚,是的话就替换掉,这样就能获得更大的利润。
但是怎么每次都能挑出一个最便宜的呢?其实priority_queue会告诉你什么叫堆,毕竟不可能还拉个数组一直排序吧。
每次如果可以直接做,就把他直接丢进小根堆,当塞不下的时候,直接查看堆顶也就是最廉价的工作,看换不换,换的话就把堆顶给弹出去,然后把目前这个工作再塞进去就行了。
时间复杂度O(n log n)
#include<bits/stdc++.h>
using namespace std;
struct node{long long d,p;
}a[100005];
bool cmp(node x,node y){return x.d<y.d;
}
priority_queue<int,vector<int>,greater<int> > q;//小根堆
int main(){int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i].d>>a[i].p;}sort(a+1,a+1+n,cmp);//将a数组按截至日期排序long long ans=0,cnt=0;//最终答案,已做工作数目for(int i=1;i<=n;i++){if(a[i].d>cnt){//如果还可以做ans+=a[i].p;//加上利润cnt++;//多做了一项q.push(a[i].p);//塞进堆}else if(a[i].p>q.top()){//如果这个工作比目前已经做了的工作中最便宜的更赚ans-=q.top();//去掉已经做了的工作中最便宜的利润ans+=a[i].p;//加上这个工作的利润q.pop();//弹掉堆顶q.push(a[i].p);//塞进去}}cout<<ans;return 0;
}