【贪心】 The Lazy Programmer

传送门

题意

\(n\)个合同,每个合同的截止日期是\(d_{i}\),一个程序员,完成第\(i\)个合同的时间是\(b_{i}\),对于合同\(i\),如果给他\(x\)元钱,他完成合同i的时间就会变成\(b_{i}-a_{i}\times x\),求最少的花费,使程序员能按时完成所有合同

数据范围

\(1 \leq n \leq 10^{5}\)
\(1 \leq a_{i},b_{i} \leq 10^{5}\)
\(1 \leq d_{i} \leq 10^{9}\)

题解

所有的合同必须完成,按照合同的规定日期排序,然后记录一个总时间,一个键值为\(a\)的大根堆,遍历合同,加上当前合同所需要的时间,当总时间超过当前合同期限就不断取出大根堆顶的,如果当前超出的时间大于堆顶订单剩余的时间,就将这个时间去掉,否则只去掉多出时间的,将减的那个订单剩余的再入堆

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fi first
#define se second 
#define ll long long
#define pb push_back
typedef pair<long long,long long> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef double db;
typedef long double ldb;
const ll mod=1e9+7;
const int N=1e5+10;
struct Node{
    int a,b,d;
    bool operator <(const Node &x) const{
        return a<x.a;
    }
}e[N];
bool cmp(Node a,Node b){
    return a.d<b.d;
}
int n;
int main(){
    priority_queue<Node>heap;
    scanf("%d",&n);
    
    rep(i,0,n) scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].d);
    sort(e,e+n,cmp);
    
    ldb ans=0;
    int now=0;

    rep(i,0,n){
        now += e[i].b;
        heap.push(e[i]);

        while(now > e[i].d && heap.size()){
            Node t = heap.top();
            heap.pop();

            if(now - e[i].d >= t.b){
                now -= t.b;
                ans += (ldb) t.b/t.a;
            } 
            else{
                ans += (ldb) (now - e[i].d) / t.a;
                t.b -= (now-e[i].d); 
                now = e[i].d;
                heap.push(t); 
            }
        }
    }
    printf("%.2llf\n",ans);
}

posted @ 2020-06-14 02:23  Hyx'  阅读(67)  评论(0)    收藏  举报