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% 的数据,有 1≤n,m≤500 000;1≤o≤min(n,m);1≤ci,pi,vi,di≤109,保证 ∀1≤i,j≤n,若pi<pj,则ci≤cj。
分析:
很容易想到的贪心,优先选择价值大且人数少的订单,对于每一个订单又优先选择容量小且花费小的房间。
所以先对房间和订单排序,房间按照容量与花费排序,订单按价值和人数排序。然后二分查找找到一个人数足够花费最小的房间,记录得到的收益,然后对所有收益排序取最大的$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<<'\n';
//for(int i=1; i<=m; ++i) cout<<b[i].val<<' '<<b[i].num<<'\n';
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\n",ans);
return 0;
}
来源:oschina
链接:https://my.oschina.net/u/4260070/blog/3433277