zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      题目传送门

    Hotel

    题目描述

    你经营着一家旅馆,这家旅馆有 n 个房间,每个房间有维护费用和容量。其中第 i 个房间的维护费用为 ci,容量为 pi 人。

    现在有 m 个订单,每个订单有两个参数:vi,di ,其中 vi 表示这个订单支付的租金,di​​ 表示人数。

    你现在得要合理选择一些订单,并放弃其他订单,使得每个选择的订单被安排在同一间房间内,且人数不超过这个房间的容量限制。当然,两个不同的订单也不能被安排在同一间房间内。

    现在你想要知道,在最多选出o 个订单时的最大收益。一个方案的收益的定义为,选出的订单的租金和,减去选出的房间的维护费用和。

    输入格式

    第一行三个空格隔开的整数n,m,o 。

    接下来 n 行,每行两个空格隔开的整数 ci,pi

    接下来 m 行,每行两个空格隔开的整数 vi,di

    输出格式

    一行一个整数表示最大收益。注意答案可能很大。

    输入输出样例

    输入

    3 2 2
    150 2
    400 3
    100 2
    200 1
    700 3
    输出 
    400

    说明/提示

    样例 11 解释

    可以将第一个订单安排至第三个房间,将第二个订单安排至第二个房间。

    数据范围

    对于 100% 的数据,有 1n,m500 000;1omin(n,m);1ci,pi,vi,di109,保证 1i,jn,若pi<pj,则cicj


      分析:

      很容易想到的贪心,优先选择价值大且人数少的订单,对于每一个订单又优先选择容量小且花费小的房间。

      所以先对房间和订单排序,房间按照容量与花费排序,订单按价值和人数排序。然后二分查找找到一个人数足够花费最小的房间,记录得到的收益,然后对所有收益排序取最大的$o$个。

      但问题在于一个房间可能已经被之前的订单占用了,所以用并查集维护一下,如果一个房间$x$被使用了,就令$fa[x]$等于$x-1$,因为显然这样是最优的。当然注意一下当搜到的房间的$fa$为$0$时不能记录。

      Code:

    //It is made by HolseLee on 11th Aug 2019
    //Luogu.org P4698
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=5e5+7;
    int n,m,o,fa[N],mon[N];
    long long ans;
    struct Room {
        int cos,p;
        bool operator < ( const Room A ) const {
            return p==A.p ? cos>A.cos : p>A.p; 
        }
    }a[N];
    struct Custom {
        int val,num;
        bool operator < ( const Custom A ) const {
            return val==A.val ? num<A.num : val>A.val;
        }
    }b[N];
    
    inline int read()
    {
        int x=0; char ch=getchar();
        while( ch<'0' || ch>'9' ) ch=getchar();
        while( ch>='0' && ch<='9' ) {
            x=x*10+ch-'0'; ch=getchar();
        }
        return x;
    }
    
    int search(int v)
    {
        int l=1, r=n, mid, ret=0;
        while( l<=r ) {
            mid=l+r>>1;
            if( a[mid].p>=v ) ret=mid, l=mid+1;
            else r=mid-1;
        }
        return ret;
    }
    
    int find(int x)
    {
        return fa[x]==x ? x : fa[x]=find(fa[x]);
    }
    
    int main()
    {
        n=read(), m=read(), o=read();
        for(int i=1; i<=n; ++i) {
            a[i].cos=read(), a[i].p=read(); fa[i]=i;
        }
        for(int i=1; i<=m; ++i) {
            b[i].val=read(), b[i].num=read();
        }
        sort(a+1,a+n+1); sort(b+1,b+m+1);
        //for(int i=1; i<=n; ++i) cout<<a[i].cos<<' '<<a[i].p<<'
    ';
        //for(int i=1; i<=m; ++i) cout<<b[i].val<<' '<<b[i].num<<'
    ';
        int x,tot=0,sum=0;
        for(int i=1; i<=m; ++i) {
            x=search(b[i].num);
            x=find(x);
            if( x ) {
                if( b[i].val-a[x].cos<=0 ) continue;
                mon[++tot]=(b[i].val-a[x].cos);
                fa[x]=x-1;
            }
        }
        sort(mon+1,mon+tot+1);
        for(int i=tot; i>0; --i) {
            ans+=mon[i]; sum++;
            if( sum==o ) break;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    h5 input调起摄像头、摄像机、录音机
    基数排序
    快速排序 && 希尔排序 && 插入排序
    堆排序
    归并排序(Merge sort)
    动态规划:背包问题
    Chap5: question: 29
    排列 && 组合
    Chap4: question: 19
    Chap3: question: 11
  • 原文地址:https://www.cnblogs.com/cytus/p/11336939.html
Copyright © 2011-2022 走看看