[SPOJ417]The lazy programmer 题解(单调队列,贪心)
题意
有\(N\)项任务,每项任务有一个截止时间\(d\),一个完成所需时间\(b\),和一个参数\(a\),对于每一个任务,若你给他\(x\)元钱,他将会在\(b_i-a_i*x\)完成任务,现求出每个任务都必须在规定时间完成的最小花费
思路
贪心,按\(d\)从小到大排序,如果能完成就不必花钱,不然就在这个之前的任务中选一个\(a\)最大的交钱,可以证明这是最优的
优先队列维护即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std ;
const int MAXN = 1e5 + 5 ;
int T , n ;
double ans = 0 ;
struct Node {
int a , b ;
int d ;
} nod[ MAXN ] ;
struct qaq {
int ai , times ;
} ;
bool operator < ( qaq x , qaq y ) {
return x.ai < y.ai ;
}
int t ;
inline int read () {
int tot = 0 , f = 1 ; char c = getchar () ;
while ( c < '0' || c > '9' ) { if ( c == '-' ) f = -1 ; c = getchar () ; }
while ( c >= '0' && c <= '9' ) { tot = tot * 10 + c - '0' ; c = getchar () ; }
return tot * f ;
}
inline bool cmp ( Node x , Node y ) {
if ( x.d != y.d )
return x.d < y.d ;
return x.a > y.a ;
}
priority_queue < qaq > q ;
signed main () {
T = read () ;
while ( T -- ) {
ans = 0 ;
n = read () ; t = 0 ;
while ( q.size () ) q.pop () ;
for ( int i = 1 ; i <= n ; i ++ ) {
nod[ i ].a = read () ; nod[ i ].b = read () ; nod[ i ].d = read () ;
}
sort ( nod + 1 , nod + 1 + n , cmp ) ;
for ( int i = 1 ; i <= n ; i ++ ) {
q.push ( ( qaq ) { nod[ i ].a , nod[ i ].b } ) ;
// cout << t << " " << nod[ i ].b << " " << nod[ i ].d << endl ;
if ( t + nod[ i ].b <= nod[ i ].d ) { t += nod[ i ].b ; continue ; }
int tt = t + nod[ i ].b - nod[ i ].d ;
while ( tt ) {
// cout << tt << endl ;
qaq tp = q.top () ;
q.pop () ;
if ( tp.times >= tt ) {
ans += 1.0 * ( ( double ) tt / ( double ) tp.ai ) ;
q.push ( ( qaq ) { tp.ai , tp.times - tt } ) ;
tt = 0 ;
}
else {
tt -= tp.times ;
ans += 1.0 * ( double ) tp.times / ( double ) tp.ai ;
}
}
t = nod[ i ].d ;
// cout << t << " " << ans << endl ;
}
printf ( "%.2f\n" , ans ) ;
}
return 0 ;
}