【bzoj1572/Usaco2009 Open】工作安排Job——优先队列
分析:因为每个事件的代价(也就是时间)是一样的,因此很容易想到应该是贪心。但是这里我们换一种思路来做:不是从大往小选,而是从前往后选,当时间不够用时就把利润最小的舍弃掉加入当前事件的,所以这里我们要先把事件按照第一维截止时间从小到大,第二维利润从小到大排序,然后枚举1~n,开一个利润从小到大的优先队列。每次枚举到事件i,若此时优先队列的size比当前事件的截止时间小,说明此时队列里的都可以选(因为事件已经按照截止时间排序),直接入队;否则,删除队首(也就是当前利润最小的事件),然后入队。枚举完统计一下还在队列里的事件利润即可。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 const int N=1e5+10; 6 struct node{ 7 int w; 8 bool operator <(const node &p)const {return p.w<w;} 9 }; 10 struct point{ 11 int d,p; 12 }e[N]; 13 int read(){ 14 int ans=0,f=1;char c=getchar(); 15 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 16 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 17 return ans*f; 18 } 19 bool cmp(point a,point b){return a.d<b.d||(a.d==b.d&&a.p<b.p);} 20 std::priority_queue<node>q; 21 int main(){ 22 long long ans=0; 23 int n=read(); 24 for(int i=1;i<=n;i++) 25 e[i].d=read(),e[i].p=read(); 26 std::sort(e+1,e+1+n,cmp); 27 for(int i=1;i<=n;i++){ 28 if(q.size()<e[i].d)q.push((node){e[i].p}); 29 else { 30 q.pop();q.push((node){e[i].p}); 31 } 32 } 33 while(!q.empty()){ 34 ans+=q.top().w;q.pop(); 35 } 36 printf("%lld",ans); 37 return 0; 38 }