Description
有n个房间和n盏灯,你需要在每个房间里放入一盏灯。每盏灯都有一定功率,每间房间都需要不少于一定功率的灯泡才可以完全照亮。
你可以去附近的商店换新灯泡,商店里所有正整数功率的灯泡都有售。但由于背包空间有限,你至多只能换k个灯泡。
你需要找到一个合理的方案使得每个房间都被完全照亮,并在这个前提下使得总功率尽可能小。
Input
第一行两个整数n,k(1<=k<=n<=500000)。
第二行n个整数pi,表示你现有的灯泡的功率。
第三行n个整数wi,表示照亮每间房间所需要的最小功率。
Output
如果无法照亮每间房间,仅输出NIE。
否则输出最小的总功率。
Sample Input
6 2
12 1 7 5 2 10
1 4 11 4 7 5
Sample Output
33
HINT
解释:将2和10换成4和4。配对方案为1-1,4-4,4-4,5-5,7-7,11-12。
Source
鸣谢Jcvb
对于一个房间有一些满足条件的灯泡,那么为了要让更多的房间在不被替换的条件下能照明同时总功率最小,我们显然对每个房间要在已有的满足条件的灯泡里选功率最小的.
所以把房间按需求功率排序,扫一遍,扫的同时把符合条件的没扫过的灯泡功率加入一个堆heap1,然后对每个房间取堆里最小值,如果当前堆为空,那么用一次k来修改,否则的话如果当前堆非空就选最小的元素,但是同时要把这个最小元素和房间需求的差值加入另一个堆heap2中,因为有可能我们在整个过程中有k没用完,那么我们要把多余的那部分k用来减少总代价.
heap1为小根堆,heap2为大根堆
最后从heap2中选出k个最小的代价从当前已经累积的代价中扣去
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAXN 500010
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,k;
int a[MAXN],b[MAXN];
long long ans;
void in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
struct Node {int x;bool operator <(const Node& a)const {return x>a.x;}};
struct node {int x;bool operator <(const node& a)const {return x<a.x;}};
priority_queue<Node>heap1;
priority_queue<node>heap2;
int main()
{
in(n);in(k);
for (int i=1;i<=n;i++) in(a[i]);
for (int i=1;i<=n;i++) in(b[i]);
sort(a+1,a+n+1);sort(b+1,b+n+1);
for (int j=n,i=n;i;i--)
{
for (;j&&a[j]>=b[i];j--) heap1.push((Node){a[j]});
if (!heap1.empty())
{
int t=heap1.top().x;ans+=heap1.top().x;
heap1.pop();heap2.push((node){t-b[i]});continue;
}
k--;ans+=b[i];
if (k<0) {puts("NIE");return 0;}
}
while (k--) ans-=heap2.top().x,heap2.pop();
cout<<ans<<endl;
}