zoukankan      html  css  js  c++  java
  • 洛谷 [USACO09OPEN]工作调度

    题面

    读完题,我们会发现有一个很重要的信息,每件物品代价相同,但价值不同。那么我们很容易想到,在满足限制的情况下,我们肯定会选择价值尽可能大的物品。

    我们可否用背包来实现呢,答案是否定的,或者说我不会QwQ

    那么,我们来看看贪心

    由于物品的代价相同,那么当物品之间冲突时,我们留下价值大者,必定最优。因为每件物品代价都是1,那么不可能出现因为放入一件物品,而挤掉了两件物品的可能,所以一定是单点比较,没有什么求和之类的

    对于价值一件物品被放入的越晚,影响也就越小,那么我们就要尽可能晚的放入物品

    我们用0表示这一秒有任务,1表示没有。那么我们按照价值排序,寻找(1)~(d[i])中最靠右的0,将他变成1,答案加上当前物品的价值即可

    详见代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cctype>
    #define ll long long
    #define gc getchar
    #define maxn 1000005
    using namespace std;
    
    inline ll read(){
        ll a=0;int f=0;char p=gc();
        while(!isdigit(p)){f|=p=='-';p=gc();}
        while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
        return f?-a:a;
    }
    
    struct ahaha{
        int w,b;
        inline bool friend operator<(const ahaha &x,const ahaha &y){
            if(x.w!=y.w)return x.w>y.w;
            return x.b<y.b;
        }
    }q[maxn];
    
    int n,cnt,b[maxn];
    ll ans;
    int tree[maxn];   //利用树状数组修改及查询前缀和
    #define lowbit(x) x&-x
    inline void add(int a,int k){
        while(k<=n){
            tree[k]+=a;
            k+=lowbit(k);
        }
    }
    int query(int k){
        int sum=0;
        while(k){
            sum+=tree[k];
            k-=lowbit(k);
        }return sum;
    }
    
    inline void solve(int i){
        int sum=query(q[i].b);    //在当前物品截止时间前,放入了多少物品
        if(sum==b[q[i].b])return;  //如果已经放满,则返回
        int l=1,r=q[i].b;
        while(l<r){    //二分查找最靠右的0
            int m=l+r>>1;
            int ss=query(m);
            if(sum-ss==b[r]-b[m]){
                r=m;sum=ss;
            }
            else
                l=m+1;
        }ans+=q[i].w;add(1,l);
    }
    
    int main(){
        n=read();
        for(int i=1;i<=n;++i)
            b[++cnt]=q[i].b=read(),q[i].w=read();
        sort(b+1,b+cnt+1);cnt=unique(b+1,b+cnt+1)-b-1;
        for(int i=1;i<=n;++i)    //先将截止时间离散化,我们把总的时间分为若干时间段,每段时间只有一个时间点为截止时间
            q[i].b=lower_bound(b+1,b+cnt+1,q[i].b)-b;
        sort(q+1,q+n+1);    //按照权值排序
        for(int i=1;i<=n;++i)
            solve(i);
        printf("%lld",ans);
        return 0;
    }
    
  • 相关阅读:
    c#读取.config文件内容
    c# 读取配置文件方法
    C# Log4net详细说明
    C# 运算符集
    LeetCode 69_ x 的平方根
    LeetCode 172 _ 阶乘后的零
    LeetCode 171 _ Excel表列序号
    LeetCode 88 _ 合并两个有序数组
    LeetCode 581 _ 最短无序连续子数组
    LeetCode 283 _ 移动零
  • 原文地址:https://www.cnblogs.com/hanruyun/p/9874953.html
Copyright © 2011-2022 走看看