bzoj 1029 [JSOI2007]建筑抢修
优先队列+贪心
先以t2排序,依次枚举,若当前时间+t1<=t2,则累计答案,并将这个建筑扔到大根堆中去
否则,在之前选过修理的建筑中选出t1最大的那个元素,与当前元素作比较,若当前的t1较小,则当前方案更优,扔出队首元素,替换成当前建筑
#include <bits/stdc++.h> #define m_k make_pair #define ll long long using namespace std; ll n,ti,ans; struct node { ll t1,t2; }sh[200000]; priority_queue <pair<ll,int> > q;//大根堆 bool cmp(node a,node b) { return (a.t2<b.t2 || (a.t2==b.t2 && a.t1<b.t1));//以t2排序 } int main() { scanf("%lld",&n); for (int i=1;i<=n;i++) scanf("%lld%lld",&sh[i].t1,&sh[i].t2); sort(sh+1,sh+1+n,cmp); for (int i=1;i<=n;i++) { if (ti+sh[i].t1<=sh[i].t2) { ans++; ti+=sh[i].t1; q.push(m_k(sh[i].t1,i));//选择修理 } else { int f; f=q.top().second; if (sh[i].t1>=sh[f].t1) continue; if (ti+sh[i].t1-sh[f].t1<=sh[i].t2) { ti+=sh[i].t1-sh[f].t1; q.pop(); q.push(m_k(sh[i].t1,i));//替换 } } } printf("%lld\n",ans); }