传送门:牛客练习赛40
题面:
小A手头有 n 份任务,他可以以任意顺序完成这些任务,只有完成当前的任务后,他才能做下一个任务
第 i 个任务需要花费 x_i 的时间,同时完成第 i 个任务的时间不能晚于 y_i ,时间掌控者向小A提出了一个条件:如果完成第 i 个任务的时间本应是 t ,但小A支付 m 个金币的话,他可以帮助小A在 t-m*z_i 时刻完成第 i 个任务, z_i 是时间参数,会在输入中给出
小A想按时完成所有任务,请你帮他制定一个花费金币最少的方案
注意:不能使得某个任务的花费时间小于 0 ,花费的金币可以不是整数
思路:
首先不难想到一个贪心策略:
1.优先完成截止时间靠前的任务。(以y[i]为关键字,从小到大排序,从左到右处理)
2.如果超出截止时间(t > y[i]),花费尽量少的金币缩短时间( ans += (t-y[i]) / z[i])
这样的贪心策略是存在问题的。如果靠后的任务不够时间完成,同时这个任务的 z 较小,而前面存在 z 特别大的任务,我们应该支付(更少的)金币去缩短前面的时间。
那么我们对上面的贪心策略做出修改:
1.时间充足的情况下(t+x[i] <= y[i]), 优先完成截止时间靠前的任务.(t += x[i])
2.如果超出截止时间(t > y[i]), 找出前面还能缩短时间 且 z[i] 最大的。
这样一来,正确性上没有问题了,但每次暴力查找能够缩短时间且z[i]最大的,复杂度撑不住。
事实上,我们应该想到,最适合维护这个东西的就是堆(priority_queue)了
代码仅供参考:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 typedef pair<ll,ll> pii; 6 #define ____ ios::sync_with_stdio(false);cin.tie(0); 7 #define fir first 8 #define sec second 9 #define mkp make_pair 10 #define pb push_back 11 #define lson l,mid,p<<1 12 #define rson mid+1,r,p<<1|1 13 const ll INF = (1LL<<60) - 1; 14 const double eps = 1e-9; 15 //head 16 const int maxn = 2e5 + 5; 17 struct Node{ 18 int k,t,ddl; 19 bool operator < (const Node & rhs) const { 20 return ddl < rhs.ddl; 21 } 22 } a[maxn]; 23 struct node{ 24 ll k,t; 25 node(double k,double t):k(k),t(t){}; 26 node(){}; 27 bool operator < (const node & rhs) const { 28 return k < rhs.k; 29 } 30 }; 31 int n; 32 int main(){ 33 //freopen("data.in","r",stdin); 34 ____ 35 cin >> n; 36 for(int i = 1; i <= n; i++){ 37 cin >> a[i].k >> a[i].t >> a[i].ddl; 38 } 39 sort(a+1, a+n+1); 40 priority_queue<node> q; 41 ll t = 0; 42 double ans = 0; 43 for(int i = 1; i <= n; i++){ 44 t += a[i].t; 45 ll t_in_i = a[i].t; 46 if(t > a[i].ddl){ 47 while((!q.empty()) && a[i].k < q.top().k){ 48 node u = q.top(); 49 q.pop(); 50 if(u.t > t-a[i].ddl){ 51 u.t -= t-a[i].ddl; 52 ans += double(t-a[i].ddl)/u.k; 53 t = a[i].ddl; 54 if(u.t){ 55 q.push(u); 56 } 57 break; 58 } 59 else{ 60 t -= u.t; 61 ans += double(u.t)/u.k; 62 } 63 } 64 if(t > a[i].ddl){ 65 ans += double(t - a[i].ddl)/a[i].k; 66 t_in_i -= t - a[i].ddl; 67 t = a[i].ddl; 68 } 69 } 70 if(t_in_i){ 71 q.push(node(a[i].k,t_in_i)); 72 } 73 } 74 cout << fixed << setprecision(1) << ans << endl; 75 return 0; 76 } 77