您的位置:首页 > Web前端 > JavaScript

[BZOJ 1029] JSOI 2007 建筑抢修 · 贪心+堆

2017-07-23 16:17 423 查看
这题很类似线段覆盖和工作安排,因此考虑用贪心,但是贪心肯定是会被卡的,所以考虑优化。

假设已经花费了now个单位时间,那么对于当前t号建筑,有两种情况:

1.now+t.cost<=t.deadline,那么就直接加上去

2.找到之前已经修过的建筑中,花费时间最多的p号建筑,如果p.cost>t.cost,那么再判断一下用t来替换p是否可行,即now+t.cost-p.cost<=t.deadline

这个的意义就相当于线段覆盖中,把t和p分别看成两条线段,并且t的长度小于p的长度,如果用t换掉p,那么必然会多出一段空白,就可以把后面的线段再向前挪,虽然这次替换没有增加线段的数量,但是为后面可能加进来的线段提供了更多空间。

找花费最大的建筑用一个大根堆优化一下。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define f(i,x,y) for (int i=x;i<=y;i++)

const int N=1e6;
typedef long long ll;
int n,ans;
ll now;
struct arr{
ll s,t;
}a
;
priority_queue<ll> heap;

bool cmp(const arr A, const arr B){
return A.t<B.t;
}

int main(){
scanf("%d",&n);
f(i,1,n)
scanf("%lld%lld",&a[i].s,&a[i].t);
sort(a+1,a+n+1,cmp);
now=0;ans=0;

f(i,1,n){
if (now+a[i].s<=a[i].t)
now+=a[i].s,
heap.push(a[i].s),
ans++;
else if (a[i].s<heap.top() && now+a[i].s-heap.top()<=a[i].t){
now-=heap.top()-a[i].s;
heap.pop();
heap.push(a[i].s);
}
}
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: