有n个房间和n盏灯,你需要在每个房间里放入一盏灯。每盏灯都有一定功率,每间房间都需要不少于一定功率的灯泡才可以完全照亮。
你可以去附近的商店换新灯泡,商店里所有正整数功率的灯泡都有售。但由于背包空间有限,你至多只能换k个灯泡。
你需要找到一个合理的方案使得每个房间都被完全照亮,并在这个前提下使得总功率尽可能小。
不错的贪心。
首先考虑当前灯泡跟新尽可能更新的
然后每个不能的自然就是其的值。
然后如果k还有剩的你在开一个multiset存差
然后从大到小维护
这个贪心似乎可以反悔?雾
HZY费用流72分
注意开LL
不用堆是因为:堆不能回收内存(它不是用vector写的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
typedef int INT;
#define int long long
const int N=1e6+10;
multiset<int>Up,Down;
int A[N];
int B[N];
int n,k;
int ans=0;
INT main(){
freopen("zarowki.in","r",stdin);
freopen("zarowki.out","w",stdout);
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;++i){
scanf("%lld",&B[i]);
}
for(int i=1;i<=n;++i){
scanf("%lld",&A[i]);
Up.insert(A[i]);
}
sort(B+1,B+1+n);
for(int i=1;i<=n;++i){
multiset<int>:: iterator It;
It=Up.upper_bound(B[i]);
if(It==Up.begin())continue;
--It;
int x=*It;
Up.erase(Up.find(x));
ans+=B[i];
Down.insert(B[i]-x);
}
if(Up.size()>k)cout<<"NIE";
else{
int cnt=0;
multiset<int>:: iterator It;
It=Up.begin();
for(;It!=Up.end();++It){
ans+=*It;
++cnt;
}
for(int i=cnt+1;i<=k;++i){
It=Down.end();
--It;
int x=*It;
ans-=x;
Down.erase(Down.find(x));
}
cout<<ans;
}
return 0;
}